diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 45a529ff3d23..2a57fb8ff01b 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -145,6 +145,7 @@ binding.setVariable("loadProject", { def compilerOptions = JpsJavaExtensionService.instance.getOrCreateCompilerConfiguration(project).currentCompilerOptions compilerOptions.GENERATE_NO_WARNINGS = true compilerOptions.DEPRECATION = false + compilerOptions.ADDITIONAL_OPTIONS_STRING = compilerOptions.ADDITIONAL_OPTIONS_STRING.replace("-Xlint:unchecked", "") }) boolean hasSourceRoots(JpsModule module) { diff --git a/java/compiler/javac2/src/com/intellij/ant/ClassFilterAnnotationRegexp.java b/java/compiler/javac2/src/com/intellij/ant/ClassFilterAnnotationRegexp.java new file mode 100644 index 000000000000..bb69d806b570 --- /dev/null +++ b/java/compiler/javac2/src/com/intellij/ant/ClassFilterAnnotationRegexp.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2014 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.ant; + +import org.apache.tools.ant.types.RegularExpression; + +/** + * A pattern which is used to skip NotNull assertion instrumentation on classes that have at least one annotation matching this pattern. + * + * Example usage: + * + * + * + * + */ +public class ClassFilterAnnotationRegexp extends RegularExpression { +} diff --git a/java/compiler/javac2/src/com/intellij/ant/Javac2.java b/java/compiler/javac2/src/com/intellij/ant/Javac2.java index e5b8aee7130a..d41e5dc70ebd 100644 --- a/java/compiler/javac2/src/com/intellij/ant/Javac2.java +++ b/java/compiler/javac2/src/com/intellij/ant/Javac2.java @@ -25,10 +25,8 @@ import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Javac; import org.apache.tools.ant.types.Path; -import org.jetbrains.org.objectweb.asm.ClassReader; -import org.jetbrains.org.objectweb.asm.ClassVisitor; -import org.jetbrains.org.objectweb.asm.ClassWriter; -import org.jetbrains.org.objectweb.asm.Opcodes; +import org.apache.tools.ant.util.regexp.Regexp; +import org.jetbrains.org.objectweb.asm.*; import java.io.*; import java.net.MalformedURLException; @@ -40,6 +38,7 @@ public class Javac2 extends Javac { private ArrayList myFormFiles; private List myNestedFormPathList; private boolean instrumentNotNull = true; + private List myClassFilterAnnotationRegexpList = new ArrayList(0); public Javac2() { } @@ -75,6 +74,16 @@ public class Javac2 extends Javac { this.instrumentNotNull = instrumentNotNull; } + /** + * Allows to specify patterns of annotation class names to skip NotNull instrumentation on classes which have at least one + * annotation matching at least one of the given patterns + * + * @param regexp the regular expression for JVM internal name (slash-separated) of annotations + */ + public void add(final ClassFilterAnnotationRegexp regexp) { + myClassFilterAnnotationRegexpList.add(regexp.getRegexp(getProject())); + } + /** * The overridden setter method that warns about unsupported option. * @@ -425,8 +434,8 @@ public class Javac2 extends Javac { ClassReader reader = new ClassReader(inputStream); int version = getClassFileVersion(reader); - - if (version >= Opcodes.V1_5) { + + if (version >= Opcodes.V1_5 && !shouldBeSkippedByAnnotationPattern(reader)) { ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); if (NotNullVerifyingInstrumenter.processClassFile(reader, writer)) { @@ -471,6 +480,30 @@ public class Javac2 extends Javac { return classfileVersion[0]; } + private boolean shouldBeSkippedByAnnotationPattern(ClassReader reader) { + if (myClassFilterAnnotationRegexpList.isEmpty()) { + return false; + } + + final boolean[] result = new boolean[]{false}; + reader.accept(new ClassVisitor(Opcodes.ASM5) { + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (!result[0]) { + String internalName = Type.getType(desc).getInternalName(); + for (Regexp regexp : myClassFilterAnnotationRegexpList) { + if (regexp.matches(internalName)) { + result[0] = true; + break; + } + } + } + return null; + } + }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + + return result[0]; + } + private void fireError(final String message) { if (failOnError) { throw new BuildException(message, getLocation()); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java index 5d32e714ab89..379fcf0dcc18 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java @@ -241,7 +241,7 @@ public class FrameVariablesTree extends DebuggerTree { } final byte[] bytecodes = method.bytecodes(); if (bytecodes != null && bytecodes.length > 0) { - final int firstLocalVariableSlot = argumentCount + (method.isStatic()? 0 : 1); + final int firstLocalVariableSlot = ArgumentValueDescriptorImpl.getFirstLocalsSlot(method); final long instructionIndex = location.codeIndex(); final TIntObjectHashMap usedVars = new TIntObjectHashMap(); new InstructionParser(bytecodes, instructionIndex) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java index a92abe492c45..2e3653afaf02 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java @@ -27,6 +27,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; +import com.sun.jdi.Method; import com.sun.jdi.PrimitiveValue; import com.sun.jdi.Value; @@ -78,8 +79,7 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ if (body != null) { final StringBuilder nameBuilder = new StringBuilder(); try { - final int startSlot = params.getParametersCount() + (method.hasModifierProperty(PsiModifier.STATIC)? 0 : 1); - body.accept(new LocalVariableNameFinder(startSlot, nameBuilder)); + body.accept(new LocalVariableNameFinder(getFirstLocalsSlot(method), nameBuilder)); } finally { myName = nameBuilder.length() > 0? myDefaultName + ": " + nameBuilder.toString() : myDefaultName; @@ -93,6 +93,36 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ return myValue; } + private static int getFirstLocalsSlot(PsiMethod method) { + int startSlot = method.hasModifierProperty(PsiModifier.STATIC) ? 0 : 1; + for (PsiParameter parameter : method.getParameterList().getParameters()) { + startSlot += getTypeSlotSize(parameter.getType()); + } + return startSlot; + } + + private static int getTypeSlotSize(PsiType varType) { + if (varType == PsiType.DOUBLE || varType == PsiType.LONG) { + return 2; + } + return 1; + } + + public static int getFirstLocalsSlot(Method method) { + int firstLocalVariableSlot = method.isStatic() ? 0 : 1; + for (String type : method.argumentTypeNames()) { + firstLocalVariableSlot += getTypeSlotSize(type); + } + return firstLocalVariableSlot; + } + + private static int getTypeSlotSize(String name) { + if (PsiKeyword.DOUBLE.equals(name) || PsiKeyword.LONG.equals(name)) { + return 2; + } + return 1; + } + public String getName() { return myName; } @@ -127,8 +157,7 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ @Override public void visitLocalVariable(PsiLocalVariable variable) { appendName(variable.getName()); - final PsiType varType = variable.getType(); - myCurrentSlotIndex += (varType == PsiType.DOUBLE || varType == PsiType.LONG)? 2 : 1; + myCurrentSlotIndex += getTypeSlotSize(variable.getType()); } public void visitSynchronizedStatement(PsiSynchronizedStatement statement) { diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java index 42ed3830364a..453cbcb0d6cd 100644 --- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java +++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java @@ -26,6 +26,7 @@ import com.intellij.execution.util.ExecutionErrorDialog; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; @@ -168,7 +169,7 @@ public class JavaExecutionUtil { @Nullable public static PsiClass findMainClass(final Project project, final String mainClassName, final GlobalSearchScope scope) { - if (project.isDefault()) return null; + if (project.isDefault() || DumbService.isDumb(project)) return null; final PsiManager psiManager = PsiManager.getInstance(project); final String shortName = StringUtil.getShortName(mainClassName); final String packageName = StringUtil.getPackageName(mainClassName); diff --git a/java/idea-ui/src/com/intellij/openapi/components/impl/stores/IdeaProjectStoreImpl.java b/java/idea-ui/src/com/intellij/openapi/components/impl/stores/IdeaProjectStoreImpl.java index 2c3165451113..95a44bcad324 100644 --- a/java/idea-ui/src/com/intellij/openapi/components/impl/stores/IdeaProjectStoreImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/components/impl/stores/IdeaProjectStoreImpl.java @@ -26,14 +26,14 @@ import org.jdom.Element; import org.jetbrains.annotations.NotNull; class IdeaProjectStoreImpl extends ProjectWithModulesStoreImpl { - public IdeaProjectStoreImpl(@NotNull ProjectImpl project) { - super(project); + public IdeaProjectStoreImpl(@NotNull ProjectImpl project, @NotNull PathMacroManager pathMacroManager) { + super(project, pathMacroManager); } @NotNull @Override protected StateStorageManager createStateStorageManager() { - return new ProjectStateStorageManager(PathMacroManager.getInstance(getComponentManager()).createTrackingSubstitutor(), myProject) { + return new ProjectStateStorageManager(myPathMacroManager.createTrackingSubstitutor(), myProject) { @Override public StorageData createIprStorageData(@NotNull String filePath) { return new IdeaIprStorageData(ROOT_TAG_NAME, myProject, filePath); diff --git a/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java b/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java index 35944487e624..d8edc9c425a2 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java +++ b/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.ide.util.projectWizard.ProjectTemplateParameterFactory; import com.intellij.ide.util.projectWizard.WizardInputField; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.ui.ValidationInfo; +import com.intellij.openapi.util.io.StreamUtil; import com.intellij.platform.ProjectTemplate; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -29,7 +30,6 @@ import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Property; import com.intellij.util.xmlb.annotations.Tag; import org.jdom.Element; -import org.jdom.Namespace; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,7 +45,6 @@ import java.util.zip.ZipInputStream; */ @Tag("template") public abstract class ArchivedProjectTemplate implements ProjectTemplate { - public static final String INPUT_FIELD = "input-field"; protected final String myDisplayName; @@ -110,22 +109,26 @@ public abstract class ArchivedProjectTemplate implements ProjectTemplate { return null; } - public abstract ZipInputStream getStream() throws IOException; + public static abstract class StreamConsumer { + public abstract T consume(@NotNull ZipInputStream stream) throws IOException; + } + + public abstract void getStream(@NotNull StreamConsumer consumer) throws IOException; @Nullable public String getCategory() { return myCategory; } - public void populateFromElement(@NotNull Element element, final Namespace ns) { + public void populateFromElement(@NotNull Element element) { XmlSerializer.deserializeInto(this, element); - myInputFields = getFields(element, ns); + myInputFields = getFields(element); } - private static List getFields(Element templateElement, final Namespace ns) { + private static List getFields(Element templateElement) { //noinspection unchecked return ContainerUtil - .mapNotNull(templateElement.getChildren(INPUT_FIELD, ns), new Function() { + .mapNotNull(templateElement.getChildren(INPUT_FIELD), new Function() { @Override public WizardInputField fun(Element element) { ProjectTemplateParameterFactory factory = WizardInputField.getFactoryById(element.getText()); @@ -134,4 +137,12 @@ public abstract class ArchivedProjectTemplate implements ProjectTemplate { }); } + static void consumeZipStream(@NotNull StreamConsumer consumer, @NotNull ZipInputStream stream) throws IOException { + try { + consumer.consume(stream); + } + finally { + StreamUtil.closeStream(stream); + } + } } diff --git a/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java index 23f4e7e2db73..d57c45019f5d 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java +++ b/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java @@ -26,6 +26,7 @@ import com.intellij.platform.ProjectTemplate; import com.intellij.platform.ProjectTemplatesFactory; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.MultiMap; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -33,13 +34,17 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author Dmitry Avdeev * @since 10/1/12 */ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory { + private final static Logger LOG = Logger.getInstance(ArchivedTemplatesFactory.class); static final String ZIP = ".zip"; @@ -47,8 +52,8 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory { @NotNull @Override protected MultiMap> compute() { - MultiMap> map = new MultiMap>(); - Map urls = new HashMap(); + MultiMap> map = MultiMap.createSmartList(); + Map urls = new THashMap(); //for (IdeaPluginDescriptor plugin : plugins) { // if (!plugin.isEnabled()) continue; // try { @@ -65,9 +70,7 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory { //} URL configURL = getCustomTemplatesURL(); - if (configURL != null) { - urls.put(configURL, ClassLoader.getSystemClassLoader()); - } + urls.put(configURL, ClassLoader.getSystemClassLoader()); for (Map.Entry url : urls.entrySet()) { try { @@ -94,23 +97,23 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory { } }; + @NotNull private static URL getCustomTemplatesURL() { - String path = getCustomTemplatesPath(); try { - return new File(path).toURI().toURL(); + return new File(getCustomTemplatesPath()).toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } } + @NotNull static String getCustomTemplatesPath() { return PathManager.getConfigPath() + "/projectTemplates"; } public static File getTemplateFile(String name) { - String configURL = getCustomTemplatesPath(); - return new File(configURL + "/" + name + ".zip"); + return new File(getCustomTemplatesPath() + "/" + name + ".zip"); } @NotNull @@ -123,13 +126,11 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory { @NotNull @Override - public ProjectTemplate[] createTemplates(String group, WizardContext context) { - Collection> urls = myGroups.getValue().get(group); + public ProjectTemplate[] createTemplates(@NotNull String group, WizardContext context) { List templates = new ArrayList(); - for (Pair url : urls) { + for (Pair url : myGroups.getValue().get(group)) { try { - List children = UrlUtil.getChildrenRelativePaths(url.first); - for (String child : children) { + for (String child : UrlUtil.getChildrenRelativePaths(url.first)) { if (child.endsWith(ZIP)) { URL templateUrl = new URL(url.first.toExternalForm() + "/" + child); templates.add(new LocalArchivedTemplate(templateUrl, url.second)); @@ -152,6 +153,4 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory { public Icon getGroupIcon(String group) { return CUSTOM_GROUP.equals(group) ? AllIcons.Modules.Types.UserDefined : super.getGroupIcon(group); } - - private final static Logger LOG = Logger.getInstance(ArchivedTemplatesFactory.class); } diff --git a/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java b/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java index 8d69635b3cbb..d0b4d540fa0b 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java +++ b/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java @@ -19,14 +19,12 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.ModuleTypeManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.CharsetToolkit; import org.jdom.Document; import org.jdom.Element; -import org.jdom.Namespace; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,7 +40,6 @@ import java.util.zip.ZipInputStream; * Date: 10/1/12 */ public class LocalArchivedTemplate extends ArchivedProjectTemplate { - public static final String DESCRIPTION_PATH = Project.DIRECTORY_STORE_FOLDER + "/description.html"; static final String TEMPLATE_DESCRIPTOR = Project.DIRECTORY_STORE_FOLDER + "/project-template.xml"; @@ -56,16 +53,11 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate { myArchivePath = archivePath; myModuleType = computeModuleType(this); - String s = readEntry(new Condition() { - @Override - public boolean value(ZipEntry entry) { - return entry.getName().endsWith(TEMPLATE_DESCRIPTOR); - } - }); + String s = readEntry(TEMPLATE_DESCRIPTOR); if (s != null) { try { Element templateElement = JDOMUtil.loadDocument(s).getRootElement(); - populateFromElement(templateElement, Namespace.NO_NAMESPACE); + populateFromElement(templateElement); String iconPath = templateElement.getChildText("icon-path"); if (iconPath != null) { myIcon = IconLoader.findIcon(iconPath, classLoader); @@ -84,12 +76,7 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate { @Override public String getDescription() { - return readEntry(new Condition() { - @Override - public boolean value(ZipEntry entry) { - return entry.getName().endsWith(DESCRIPTION_PATH); - } - }); + return readEntry(DESCRIPTION_PATH); } @Override @@ -98,34 +85,29 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate { } @Nullable - String readEntry(Condition condition) { - ZipInputStream stream = null; + String readEntry(@NotNull final String endsWith) { try { - stream = getStream(); - ZipEntry entry; - while ((entry = stream.getNextEntry()) != null) { - if (condition.value(entry)) { - return StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); + getStream(new StreamConsumer() { + @Override + public String consume(@NotNull ZipInputStream stream) throws IOException { + ZipEntry entry; + while ((entry = stream.getNextEntry()) != null) { + if (entry.getName().endsWith(endsWith)) { + return StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); + } + } + return null; } - } + }); } - catch (IOException e) { - return null; - } - finally { - StreamUtil.closeStream(stream); + catch (IOException ignored) { } return null; } @NotNull private static ModuleType computeModuleType(LocalArchivedTemplate template) { - String iml = template.readEntry(new Condition() { - @Override - public boolean value(ZipEntry entry) { - return entry.getName().endsWith(".iml"); - } - }); + String iml = template.readEntry(".iml"); if (iml == null) return ModuleType.EMPTY; try { Document document = JDOMUtil.loadDocument(iml); @@ -143,8 +125,8 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate { } @Override - public ZipInputStream getStream() throws IOException { - return new ZipInputStream(myArchivePath.openStream()); + public void getStream(@NotNull StreamConsumer consumer) throws IOException { + consumeZipStream(consumer, new ZipInputStream(myArchivePath.openStream())); } public URL getArchivePath() { diff --git a/java/idea-ui/src/com/intellij/platform/templates/ManageProjectTemplatesDialog.java b/java/idea-ui/src/com/intellij/platform/templates/ManageProjectTemplatesDialog.java index 3a8a97b91cef..c9b87cd80945 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/ManageProjectTemplatesDialog.java +++ b/java/idea-ui/src/com/intellij/platform/templates/ManageProjectTemplatesDialog.java @@ -19,6 +19,7 @@ import com.intellij.CommonBundle; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.platform.ProjectTemplate; import com.intellij.platform.ProjectTemplatesFactory; import com.intellij.ui.CollectionListModel; @@ -35,7 +36,6 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.io.File; -import java.net.URL; import java.util.Arrays; /** @@ -53,18 +53,16 @@ class ManageProjectTemplatesDialog extends DialogWrapper { setTitle("Manage Project Templates"); final ProjectTemplate[] templates = new ArchivedTemplatesFactory().createTemplates(ProjectTemplatesFactory.CUSTOM_GROUP, new WizardContext(null)); - final CollectionListModel model = new CollectionListModel(Arrays.asList(templates)) { + myTemplatesList = new JBList(new CollectionListModel(Arrays.asList(templates)) { @Override public void remove(int index) { ProjectTemplate template = getElementAt(index); super.remove(index); if (template instanceof LocalArchivedTemplate) { - URL path = ((LocalArchivedTemplate)template).getArchivePath(); - new File(path.getPath()).delete(); + FileUtil.delete(new File(((LocalArchivedTemplate)template).getArchivePath().getPath())); } } - }; - myTemplatesList = new JBList(model); + }); myTemplatesList.setEmptyText("No user-defined project templates"); myTemplatesList.setPreferredSize(new Dimension(300, 100)); myTemplatesList.setCellRenderer(new ColoredListCellRenderer() { diff --git a/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java index 956108b951f0..9a2d7dcd2658 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java +++ b/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java @@ -24,25 +24,20 @@ import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.ModuleTypeManager; import com.intellij.openapi.util.ClearableLazyValue; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.io.StreamUtil; -import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.platform.ProjectTemplate; import com.intellij.platform.ProjectTemplatesFactory; import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; -import com.intellij.util.net.HttpConfigurable; +import com.intellij.util.io.HttpRequests; import org.jdom.Element; import org.jdom.JDOMException; -import org.jdom.Namespace; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; import java.util.Collection; import java.util.List; import java.util.zip.ZipInputStream; @@ -52,23 +47,39 @@ import java.util.zip.ZipInputStream; * Date: 11/14/12 */ public class RemoteTemplatesFactory extends ProjectTemplatesFactory { + private final static Logger LOG = Logger.getInstance(RemoteTemplatesFactory.class); - private static final String URL = "http://download.jetbrains.com/idea/project_templates/"; + private static final String URL = "https://download.jetbrains.com/idea/project_templates/"; public static final String TEMPLATE = "template"; public static final String INPUT_DEFAULT = "default"; - public static final Function ELEMENT_STRING_FUNCTION = new Function() { - @Override - public String fun(Element element) { - return element.getText(); - } - }; private final ClearableLazyValue> myTemplates = new ClearableLazyValue>() { @NotNull @Override protected MultiMap compute() { - return getTemplates(); + try { + return HttpRequests.request(URL + ApplicationInfo.getInstance().getBuild().getProductCode() + "_templates.xml") + .connect(new HttpRequests.RequestProcessor>() { + @Override + public MultiMap process(@NotNull HttpRequests.Request request) throws IOException { + try { + return create(JDOMUtil.load(request.getReader())); + } + catch (JDOMException e) { + LOG.error(e); + return MultiMap.emptyInstance(); + } + } + }); + } + catch (IOException e) { // timeouts, lost connection etc + LOG.info(e); + } + catch (Exception e) { + LOG.error(e); + } + return MultiMap.emptyInstance(); } }; @@ -81,98 +92,56 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory { @NotNull @Override - public ProjectTemplate[] createTemplates(String group, WizardContext context) { + public ProjectTemplate[] createTemplates(@NotNull String group, WizardContext context) { Collection templates = myTemplates.getValue().get(group); return templates.toArray(new ProjectTemplate[templates.size()]); } - private static MultiMap getTemplates() { - InputStream stream = null; - HttpURLConnection connection = null; - String code = ApplicationInfo.getInstance().getBuild().getProductCode(); - try { - connection = getConnection(code + "_templates.xml"); - stream = connection.getInputStream(); - String text = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); - return createFromText(text); - } - catch (IOException ex) { // timeouts, lost connection etc - LOG.info(ex); - return MultiMap.emptyInstance(); - } - catch (Exception e) { - LOG.error(e); - return MultiMap.emptyInstance(); - } - finally { - StreamUtil.closeStream(stream); - if (connection != null) { - connection.disconnect(); - } - } + @NotNull + @TestOnly + public static MultiMap createFromText(@NotNull String value) throws IOException, JDOMException { + return create(JDOMUtil.loadDocument(value).getRootElement()); } - @SuppressWarnings("unchecked") - public static MultiMap createFromText(String text) throws IOException, JDOMException { - - MultiMap map = new MultiMap(); - Element rootElement = JDOMUtil.loadDocument(text).getRootElement(); - List templates = createGroupTemplates(rootElement, Namespace.NO_NAMESPACE); - for (ArchivedProjectTemplate template : templates) { + @NotNull + private static MultiMap create(@NotNull Element element) throws IOException, JDOMException { + MultiMap map = MultiMap.createSmartList(); + for (ArchivedProjectTemplate template : createGroupTemplates(element)) { map.putValue(template.getCategory(), template); } return map; } @SuppressWarnings("unchecked") - private static List createGroupTemplates(Element groupElement, final Namespace ns) { - List elements = groupElement.getChildren(TEMPLATE, ns); - + private static List createGroupTemplates(Element groupElement) { + List elements = groupElement.getChildren(TEMPLATE); return ContainerUtil.mapNotNull(elements, new NullableFunction() { @Override public ArchivedProjectTemplate fun(final Element element) { - - if (!checkRequiredPlugins(element, ns)) return null; + if (!checkRequiredPlugins(element)) return null; String type = element.getChildText("moduleType"); final ModuleType moduleType = ModuleTypeManager.getInstance().findByID(type); - final String path = element.getChildText("path", ns); - final String description = element.getChildTextTrim("description", ns); - String name = element.getChildTextTrim("name", ns); + final String path = element.getChildText("path"); + final String description = element.getChildTextTrim("description"); + String name = element.getChildTextTrim("name"); RemoteProjectTemplate template = new RemoteProjectTemplate(name, element, moduleType, path, description); - template.populateFromElement(element, ns); + template.populateFromElement(element); return template; } }); } - public static List getFrameworks(Element element) { - List frameworks = element.getChildren("framework"); - return ContainerUtil.map(frameworks, ELEMENT_STRING_FUNCTION); - } - - private static boolean checkRequiredPlugins(Element element, Namespace ns) { - @SuppressWarnings("unchecked") List plugins = element.getChildren("requiredPlugin", ns); - for (Element plugin : plugins) { - String id = plugin.getTextTrim(); - if (!PluginManager.isPluginInstalled(PluginId.getId(id))) { + private static boolean checkRequiredPlugins(Element element) { + for (Element plugin : element.getChildren("requiredPlugin")) { + if (!PluginManager.isPluginInstalled(PluginId.getId(plugin.getTextTrim()))) { return false; } } return true; } - private static HttpURLConnection getConnection(String path) throws IOException { - HttpURLConnection connection = HttpConfigurable.getInstance().openHttpConnection(URL + path); - connection.setConnectTimeout(2000); - connection.setReadTimeout(2000); - connection.connect(); - return connection; - } - - private final static Logger LOG = Logger.getInstance(RemoteTemplatesFactory.class); - private static class RemoteProjectTemplate extends ArchivedProjectTemplate { private final ModuleType myModuleType; private final String myPath; @@ -194,15 +163,14 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory { } @Override - public ZipInputStream getStream() throws IOException { - final HttpURLConnection connection = getConnection(myPath); - return new ZipInputStream(connection.getInputStream()) { + public void getStream(@NotNull final StreamConsumer consumer) throws IOException { + HttpRequests.request(URL + myPath).connect(new HttpRequests.RequestProcessor() { @Override - public void close() throws IOException { - super.close(); - connection.disconnect(); + public Void process(@NotNull HttpRequests.Request request) throws IOException { + consumeZipStream(consumer, new ZipInputStream(request.getInputStream())); + return null; } - }; + }); } @Nullable diff --git a/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java b/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java index 9771d58b625f..475cf4e42c05 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java +++ b/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java @@ -40,7 +40,6 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtilRt; -import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtilRt; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; @@ -200,12 +199,9 @@ public class TemplateModuleBuilder extends ModuleBuilder { } private void unzip(final @Nullable String projectName, String path, final boolean moduleMode) { - File dir = new File(path); - ZipInputStream zipInputStream = null; final WizardInputField basePackage = getBasePackageField(); try { - zipInputStream = myTemplate.getStream(); - NullableFunction pathConvertor = new NullableFunction() { + final NullableFunction pathConvertor = new NullableFunction() { @Nullable @Override public String fun(String path) { @@ -216,13 +212,22 @@ public class TemplateModuleBuilder extends ModuleBuilder { return path; } }; - ZipUtil.unzip(ProgressManager.getInstance().getProgressIndicator(), dir, zipInputStream, pathConvertor, new ZipUtil.ContentProcessor() { + + final File dir = new File(path); + myTemplate.getStream(new ArchivedProjectTemplate.StreamConsumer() { @Override - public byte[] processContent(byte[] content, File file) throws IOException { - FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(FileUtilRt.getExtension(file.getName())); - return fileType.isBinary() ? content : processTemplates(projectName, new String(content, CharsetToolkit.UTF8_CHARSET), file); + public Void consume(@NotNull ZipInputStream stream) throws IOException { + ZipUtil.unzip(ProgressManager.getInstance().getProgressIndicator(), dir, stream, pathConvertor, new ZipUtil.ContentProcessor() { + @Override + public byte[] processContent(byte[] content, File file) throws IOException { + FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(FileUtilRt.getExtension(file.getName())); + return fileType.isBinary() ? content : processTemplates(projectName, new String(content, CharsetToolkit.UTF8_CHARSET), file); + } + }, true); + return null; } - }, true); + }); + String iml = ContainerUtil.find(dir.list(), new Condition() { @Override public boolean value(String s) { @@ -245,9 +250,6 @@ public class TemplateModuleBuilder extends ModuleBuilder { catch (IOException e) { throw new RuntimeException(e); } - finally { - StreamUtil.closeStream(zipInputStream); - } } private static String getPathFragment(String value) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java index ee81e7c09fd3..c626a96f8222 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java @@ -22,6 +22,7 @@ import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PropertyUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +38,8 @@ public class PurityInference { if (!InferenceFromSourceUtil.shouldInferFromSource(method) || method.getReturnType() == PsiType.VOID || method.getBody() == null || - method.isConstructor()) { + method.isConstructor() || + PropertyUtil.isSimpleGetter(method)) { return false; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java index f3b95702eac7..e189374b2eb4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java @@ -24,6 +24,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.ui.Messages; @@ -150,7 +151,9 @@ class AddModuleDependencyFix extends OrderEntryFix { targetClasses.add(psiClass); } } - new AddImportAction(project, myReference, editor, targetClasses.toArray(new PsiClass[targetClasses.size()])).execute(); + if (!DumbService.isDumb(project)) { + new AddImportAction(project, myReference, editor, targetClasses.toArray(new PsiClass[targetClasses.size()])).execute(); + } } } }; diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java index de7261d60641..8cfadfd36c4a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java @@ -18,9 +18,9 @@ package com.intellij.codeInsight.generation; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.psi.*; import com.intellij.psi.codeStyle.*; import com.intellij.psi.search.GlobalSearchScope; @@ -234,6 +234,9 @@ public class GenerateEqualsHelper implements Runnable { @NonNls private static final MessageFormat ARRAY_COMPARER_MF = new MessageFormat("if(!java.util.Arrays.equals({1}, {0}.{1})) return false;\n"); + + @NonNls private static final MessageFormat ARRAY_DEEP_COMPARER_MF = + new MessageFormat("if(!java.util.Arrays.deepEquals({1}, {0}.{1})) return false;\n"); @NonNls private static final MessageFormat FIELD_COMPARER_MF = new MessageFormat("if({1}!=null ? !{1}.equals({0}.{1}) : {0}.{1}!= null)return false;\n"); @NonNls private static final MessageFormat NON_NULL_FIELD_COMPARER_MF = new MessageFormat("if(!{1}.equals({0}.{1}))return false;\n"); @@ -244,9 +247,14 @@ public class GenerateEqualsHelper implements Runnable { private void addArrayEquals(StringBuffer buffer, PsiField field) { final PsiType fieldType = field.getType(); if (isNestedArray(fieldType)) { - buffer.append(" "); - buffer.append(CodeInsightBundle.message("generate.equals.compare.nested.arrays.comment", field.getName())); - buffer.append("\n"); + if (JavaVersionService.getInstance().isAtLeast(field, JavaSdkVersion.JDK_1_5)) { + ARRAY_DEEP_COMPARER_MF.format(getComparerFormatParameters(field), buffer, null); + } + else { + buffer.append(" "); + buffer.append(CodeInsightBundle.message("generate.equals.compare.nested.arrays.comment", field.getName())); + buffer.append("\n"); + } return; } if (isArrayOfObjects(fieldType)) { @@ -474,7 +482,14 @@ public class GenerateEqualsHelper implements Runnable { } private static void adjustHashCodeToArrays(@NonNls StringBuilder buffer, final PsiField field, final String name) { - if (field.getType() instanceof PsiArrayType && hasArraysHashCode(field)) { + final PsiType fieldType = field.getType(); + if (fieldType instanceof PsiArrayType && + JavaVersionService.getInstance().isAtLeast(field, JavaSdkVersion.JDK_1_5)) { + if (isNestedArray(fieldType)) { + buffer.append(" "); + buffer.append("// Probably incorrect - hashCode for high dimension arrays with Arrays.hashCode"); + buffer.append("\n"); + } buffer.append("java.util.Arrays.hashCode("); buffer.append(name); buffer.append(")"); @@ -485,16 +500,6 @@ public class GenerateEqualsHelper implements Runnable { } } - private static boolean hasArraysHashCode(final PsiField field) { - // the method was added in JDK 1.5 - check for actual method presence rather than language level - Module module = ModuleUtilCore.findModuleForPsiElement(field); - if (module == null) return false; - PsiClass arraysClass = JavaPsiFacade.getInstance(field.getProject()).findClass("java.util.Arrays", module.getModuleWithLibrariesScope()); - if (arraysClass == null) return false; - final PsiMethod[] methods = arraysClass.findMethodsByName("hashCode", false); - return methods.length > 0; - } - @SuppressWarnings("HardCodedStringLiteral") private void addSuperHashCode(StringBuilder buffer) { if (mySuperHasHashCode) { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java index 035a469e500c..315f30c1e084 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java @@ -22,8 +22,11 @@ import com.intellij.codeInsight.generation.GenerateEqualsHelper; import com.intellij.ide.wizard.StepAdapter; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.psi.*; +import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.classMembers.AbstractMemberInfoModel; import com.intellij.refactoring.classMembers.MemberInfoBase; import com.intellij.refactoring.classMembers.MemberInfoTooltipManager; @@ -263,12 +266,15 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard getRoots() { Set roots= new HashSet(); - final PsiDirectory[] dirs = PackageUtil.getDirectories(getPackage(), myElement.getProject(), myModule, isLibraryElement()); + final PsiDirectory[] dirs = PackageUtil.getDirectories(getPackage(), myModule, isLibraryElement()); for (PsiDirectory each : dirs) { roots.add(each.getVirtualFile()); } diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java index 1e09187d15c6..3d73fdd48c0c 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java @@ -28,7 +28,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiPackage; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,15 +89,18 @@ public class PackageElementNode extends ProjectViewNode { if (!getSettings().isFlattenPackages()) { - final PsiPackage[] subpackages = PackageUtil.getSubpackages(aPackage, module, myProject, isLibraryElement()); + final PsiPackage[] subpackages = PackageUtil.getSubpackages(aPackage, module, isLibraryElement()); for (PsiPackage subpackage : subpackages) { PackageUtil.addPackageAsChild(children, subpackage, module, getSettings(), isLibraryElement()); } } // process only files in package's directories - final PsiDirectory[] dirs = PackageUtil.getDirectories(aPackage, myProject, module, isLibraryElement()); - for (final PsiDirectory dir : dirs) { - children.addAll(ProjectViewDirectoryHelper.getInstance(myProject).getDirectoryChildren(dir, getSettings(), false)); + final GlobalSearchScope scopeToShow = PackageUtil.getScopeToShow(aPackage.getProject(), module, isLibraryElement()); + PsiFile[] packageChildren = aPackage.getFiles(scopeToShow); + for (PsiFile file : packageChildren) { + if (file.getVirtualFile() != null) { + children.add(new PsiFileNode(getProject(), file, getSettings())); + } } return children; } @@ -163,7 +168,7 @@ public class PackageElementNode extends ProjectViewNode { if (value == null) { return VirtualFile.EMPTY_ARRAY; } - final PsiDirectory[] directories = PackageUtil.getDirectories(value.getPackage(), getProject(), value.getModule(), isLibraryElement()); + final PsiDirectory[] directories = PackageUtil.getDirectories(value.getPackage(), value.getModule(), isLibraryElement()); final VirtualFile[] result = new VirtualFile[directories.length]; for (int i = 0; i < directories.length; i++) { PsiDirectory directory = directories[i]; diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java index bcb4b3d20319..885913402e80 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java @@ -23,12 +23,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaDirectoryService; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiPackage; +import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,25 +34,18 @@ public class PackageUtil { @NotNull public static PsiPackage[] getSubpackages(@NotNull PsiPackage aPackage, @Nullable Module module, - @NotNull Project project, final boolean searchInLibraries) { - final PsiDirectory[] dirs = getDirectories(aPackage, project, module, searchInLibraries); - final Set subpackages = new HashSet(); - for (PsiDirectory dir : dirs) { - final PsiDirectory[] subdirectories = dir.getSubdirectories(); - for (PsiDirectory subdirectory : subdirectories) { - final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(subdirectory); - if (psiPackage != null) { - final String name = psiPackage.getName(); - // skip "default" subpackages as they should be attributed to other modules - // this is the case when contents of one module is nested into contents of another - if (name != null && !name.isEmpty()) { - subpackages.add(psiPackage); - } - } + final GlobalSearchScope scopeToShow = getScopeToShow(aPackage.getProject(), module, searchInLibraries); + List result = new ArrayList(); + for (PsiPackage psiPackage : aPackage.getSubPackages(scopeToShow)) { + // skip "default" subpackages as they should be attributed to other modules + // this is the case when contents of one module is nested into contents of another + final String name = psiPackage.getName(); + if (name != null && !name.isEmpty()) { + result.add(psiPackage); } } - return subpackages.toArray(new PsiPackage[subpackages.size()]); + return result.toArray(new PsiPackage[result.size()]); } public static void addPackageAsChild(@NotNull Collection children, @@ -70,7 +59,7 @@ public class PackageUtil { children.add(new PackageElementNode(project, new PackageElement(module, aPackage, inLibrary), settings)); } if (settings.isFlattenPackages() || shouldSkipPackage) { - final PsiPackage[] subpackages = getSubpackages(aPackage, module, project, inLibrary); + final PsiPackage[] subpackages = getSubpackages(aPackage, module, inLibrary); for (PsiPackage subpackage : subpackages) { addPackageAsChild(children, subpackage, module, settings, inLibrary); } @@ -82,26 +71,28 @@ public class PackageUtil { boolean strictlyEmpty, final boolean inLibrary) { final Project project = aPackage.getProject(); - final PsiDirectory[] dirs = getDirectories(aPackage, project, module, inLibrary); - for (final PsiDirectory dir : dirs) { - if (!TreeViewUtil.isEmptyMiddlePackage(dir, strictlyEmpty)) { - return false; - } + final GlobalSearchScope scopeToShow = getScopeToShow(project, module, inLibrary); + PsiElement[] children = aPackage.getFiles(scopeToShow); + if (children.length > 0) { + return false; } - return true; + PsiPackage[] subPackages = aPackage.getSubPackages(scopeToShow); + if (strictlyEmpty) { + return subPackages.length == 1; + } + return subPackages.length > 0; } @NotNull public static PsiDirectory[] getDirectories(@NotNull PsiPackage aPackage, - @NotNull Project project, @Nullable Module module, boolean inLibrary) { - final GlobalSearchScope scopeToShow = getScopeToShow(project, module, inLibrary); + final GlobalSearchScope scopeToShow = getScopeToShow(aPackage.getProject(), module, inLibrary); return aPackage.getDirectories(scopeToShow); } @NotNull - private static GlobalSearchScope getScopeToShow(@NotNull Project project, @Nullable Module module, boolean forLibraries) { + public static GlobalSearchScope getScopeToShow(@NotNull Project project, @Nullable Module module, boolean forLibraries) { if (module == null) { if (forLibraries) { return new ProjectLibrariesSearchScope(project); @@ -242,7 +233,7 @@ public class PackageUtil { @Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { - throw new IncorrectOperationException("not implemented"); + return 0; } @Override diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewModuleGroupNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewModuleGroupNode.java index 7416cd7ec6c5..0f1e1c9c9998 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewModuleGroupNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewModuleGroupNode.java @@ -39,7 +39,7 @@ public class PackageViewModuleGroupNode extends ModuleGroupNode { @Override protected AbstractTreeNode createModuleNode(Module module) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { - return createTreeNode(PackageViewModuleNode.class, module.getProject(), module, getSettings()); + return new PackageViewModuleNode(module.getProject(), module, getSettings()); } @Override diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewProjectNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewProjectNode.java index 76946c41e999..1383ef400438 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewProjectNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewProjectNode.java @@ -101,13 +101,13 @@ public class PackageViewProjectNode extends AbstractProjectNode { protected AbstractTreeNode createModuleGroup(final Module module) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { - return createTreeNode(PackageViewModuleNode.class, getProject(), module, getSettings()); + return new PackageViewModuleNode(getProject(), module, getSettings()); } @Override protected AbstractTreeNode createModuleGroupNode(final ModuleGroup moduleGroup) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { - return createTreeNode(PackageViewModuleGroupNode.class, getProject(), moduleGroup, getSettings()); + return new PackageViewModuleGroupNode(getProject(), moduleGroup, getSettings()); } @Override diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 56f376ffbf06..cf5eea20c05d 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -48,6 +48,7 @@ import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; @@ -186,8 +187,51 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext buffer.append(JavaDocUtil.getShortestClassName(aClass, aClass)); - if (aClass.hasTypeParameters()) { - PsiTypeParameter[] parms = aClass.getTypeParameters(); + generateTypeParameters(aClass, buffer); + + if (!aClass.isEnum() && !aClass.isAnnotationType()) { + PsiReferenceList extendsList = aClass.getExtendsList(); + writeExtends(aClass, buffer, extendsList == null ? PsiClassType.EMPTY_ARRAY : extendsList.getReferencedTypes()); + } + + writeImplements(aClass, buffer, aClass.getImplementsListTypes()); + + return buffer.toString(); + } + + public static void writeImplements(PsiClass aClass, StringBuilder buffer, PsiClassType[] refs) { + if (refs.length > 0) { + newLine(buffer); + buffer.append("implements "); + writeTypeRefs(aClass, buffer, refs); + } + } + + public static void writeExtends(PsiClass aClass, StringBuilder buffer, PsiClassType[] refs) { + if (refs.length > 0 || !aClass.isInterface() && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { + buffer.append(" extends "); + if (refs.length == 0) { + buffer.append("Object"); + } + else { + writeTypeRefs(aClass, buffer, refs); + } + } + } + + private static void writeTypeRefs(PsiClass aClass, StringBuilder buffer, PsiClassType[] refs) { + for (int i = 0; i < refs.length; i++) { + JavaDocInfoGenerator.generateType(buffer, refs[i], aClass, false); + + if (i < refs.length - 1) { + buffer.append(", "); + } + } + } + + public static void generateTypeParameters(PsiTypeParameterListOwner typeParameterOwner, StringBuilder buffer) { + if (typeParameterOwner.hasTypeParameters()) { + PsiTypeParameter[] parms = typeParameterOwner.getTypeParameters(); buffer.append("<"); @@ -195,14 +239,13 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext PsiTypeParameter p = parms[i]; buffer.append(p.getName()); - PsiClassType[] refs = p.getExtendsList().getReferencedTypes(); if (refs.length > 0) { buffer.append(" extends "); for (int j = 0; j < refs.length; j++) { - JavaDocInfoGenerator.generateType(buffer, refs[j], aClass, false); + JavaDocInfoGenerator.generateType(buffer, refs[j], typeParameterOwner, false); if (j < refs.length - 1) { buffer.append(" & "); @@ -217,42 +260,6 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext buffer.append(">"); } - - PsiClassType[] refs; - if (!aClass.isEnum() && !aClass.isAnnotationType()) { - PsiReferenceList extendsList = aClass.getExtendsList(); - refs = extendsList == null ? PsiClassType.EMPTY_ARRAY : extendsList.getReferencedTypes(); - if (refs.length > 0 || !aClass.isInterface() && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { - buffer.append(" extends "); - if (refs.length == 0) { - buffer.append("Object"); - } - else { - for (int i = 0; i < refs.length; i++) { - JavaDocInfoGenerator.generateType(buffer, refs[i], aClass, false); - - if (i < refs.length - 1) { - buffer.append(", "); - } - } - } - } - } - - refs = aClass.getImplementsListTypes(); - if (refs.length > 0) { - newLine(buffer); - buffer.append("implements "); - for (int i = 0; i < refs.length; i++) { - JavaDocInfoGenerator.generateType(buffer, refs[i], aClass, false); - - if (i < refs.length - 1) { - buffer.append(", "); - } - } - } - - return buffer.toString(); } @SuppressWarnings({"HardCodedStringLiteral"}) @@ -272,35 +279,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext generateModifiers(buffer, method); - PsiTypeParameter[] params = method.getTypeParameters(); - - if (params.length > 0) { - buffer.append("<"); - for (int i = 0; i < params.length; i++) { - PsiTypeParameter param = params[i]; - - buffer.append(param.getName()); - - PsiClassType[] extendees = param.getExtendsList().getReferencedTypes(); - - if (extendees.length > 0) { - buffer.append(" extends "); - - for (int j = 0; j < extendees.length; j++) { - JavaDocInfoGenerator.generateType(buffer, extendees[j], method, false); - - if (j < extendees.length - 1) { - buffer.append(" & "); - } - } - } - - if (i < params.length - 1) { - buffer.append(", "); - } - } - buffer.append("> "); - } + generateTypeParameters(method, buffer); if (method.getReturnType() != null) { JavaDocInfoGenerator.generateType(buffer, substitutor.substitute(method.getReturnType()), method, false); @@ -415,43 +394,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext .forLanguage(commentOwner.getLanguage()); if (commentOwner instanceof PsiMethod) { PsiMethod psiMethod = (PsiMethod)commentOwner; - final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); - final Map param2Description = new HashMap(); - final PsiMethod[] superMethods = psiMethod.findSuperMethods(); - for (PsiMethod superMethod : superMethods) { - final PsiDocComment comment = superMethod.getDocComment(); - if (comment != null) { - final PsiDocTag[] params = comment.findTagsByName("param"); - for (PsiDocTag param : params) { - final PsiElement[] dataElements = param.getDataElements(); - if (dataElements != null) { - String paramName = null; - for (PsiElement dataElement : dataElements) { - if (dataElement instanceof PsiDocParamRef) { - paramName = dataElement.getReference().getCanonicalText(); - break; - } - } - if (paramName != null) { - param2Description.put(paramName, param.getText()); - } - } - } - } - } - for (PsiParameter parameter : parameters) { - String description = param2Description.get(parameter.getName()); - if (description != null) { - builder.append(CodeDocumentationUtil.createDocCommentLine("", project, commenter)); - if (description.indexOf('\n') > -1) description = description.substring(0, description.lastIndexOf('\n')); - builder.append(description); - } - else { - builder.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); - builder.append(parameter.getName()); - } - builder.append(LINE_SEPARATOR); - } + generateParametersTakingDocFromSuperMethods(project, builder, commenter, psiMethod); final PsiTypeParameterList typeParameterList = psiMethod.getTypeParameterList(); if (typeParameterList != null) { @@ -478,7 +421,51 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return builder.length() > 0 ? builder.toString() : null; } - private static void createTypeParamsListComment(final StringBuilder buffer, + public static void generateParametersTakingDocFromSuperMethods(Project project, + StringBuilder builder, + CodeDocumentationAwareCommenter commenter, PsiMethod psiMethod) { + final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + final Map param2Description = new HashMap(); + final PsiMethod[] superMethods = psiMethod.findSuperMethods(); + + for (PsiMethod superMethod : superMethods) { + final PsiDocComment comment = superMethod.getDocComment(); + if (comment != null) { + final PsiDocTag[] params = comment.findTagsByName("param"); + for (PsiDocTag param : params) { + final PsiElement[] dataElements = param.getDataElements(); + if (dataElements != null) { + String paramName = null; + for (PsiElement dataElement : dataElements) { + if (dataElement instanceof PsiDocParamRef) { + paramName = dataElement.getReference().getCanonicalText(); + break; + } + } + if (paramName != null) { + param2Description.put(paramName, param.getText()); + } + } + } + } + } + + for (PsiParameter parameter : parameters) { + String description = param2Description.get(parameter.getName()); + if (description != null) { + builder.append(CodeDocumentationUtil.createDocCommentLine("", project, commenter)); + if (description.indexOf('\n') > -1) description = description.substring(0, description.lastIndexOf('\n')); + builder.append(description); + } + else { + builder.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); + builder.append(parameter.getName()); + } + builder.append(LINE_SEPARATOR); + } + } + + public static void createTypeParamsListComment(final StringBuilder buffer, final Project project, final CodeDocumentationAwareCommenter commenter, final PsiTypeParameterList typeParameterList) { @@ -491,11 +478,56 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext } @Override - public String generateDoc(final PsiElement element, final PsiElement originalElement) { + public String generateDoc(PsiElement element, PsiElement originalElement) { + if (element instanceof PsiExpressionList) { + element = element.getParent(); // for new Class() or methodCall() proceed from method call or new expression + originalElement = null; + } if (element instanceof PsiMethodCallExpression) { return getMethodCandidateInfo((PsiMethodCallExpression)element); } + // Try hard for documentation of incomplete new Class instantiation + PsiElement elt = originalElement != null ? PsiTreeUtil.prevLeaf(originalElement): element; + if (elt instanceof PsiErrorElement) elt = elt.getPrevSibling(); + else if (elt != null && !(elt instanceof PsiNewExpression)) { + elt = elt.getParent(); + } + if (elt instanceof PsiNewExpression) { + PsiClass targetClass = null; + + if (element instanceof PsiJavaCodeReferenceElement) { // new Class + PsiElement resolve = ((PsiJavaCodeReferenceElement)element).resolve(); + if (resolve instanceof PsiClass) targetClass = (PsiClass)resolve; + } else if (element instanceof PsiClass) { //Class in completion + targetClass = (PsiClass)element; + } else if (element instanceof PsiNewExpression) { // new Class() + PsiJavaCodeReferenceElement reference = ((PsiNewExpression)element).getClassReference(); + if (reference != null) { + PsiElement resolve = reference.resolve(); + if (resolve instanceof PsiClass) targetClass = (PsiClass)resolve; + } + } + + if (targetClass != null) { + PsiMethod[] constructors = targetClass.getConstructors(); + if (constructors.length > 0) { + if (constructors.length == 1) return generateDoc(constructors[0], originalElement); + @NonNls final StringBuilder sb = new StringBuilder(); + + for(PsiMethod constructor:constructors) { + final String str = PsiFormatUtil.formatMethod(constructor, PsiSubstitutor.EMPTY, + PsiFormatUtilBase.SHOW_NAME | + PsiFormatUtilBase.SHOW_TYPE | + PsiFormatUtilBase.SHOW_PARAMETERS, + PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_NAME); + createElementLink(sb, constructor, StringUtil.escapeXml(str)); + } + + return CodeInsightBundle.message("javadoc.constructor.candidates", targetClass.getName(), sb); + } + } + } //external documentation finder return generateExternalJavadoc(element); @@ -528,11 +560,15 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return null; } - private static String getMethodCandidateInfo(PsiMethodCallExpression expr) { + private String getMethodCandidateInfo(PsiMethodCallExpression expr) { final PsiResolveHelper rh = JavaPsiFacade.getInstance(expr.getProject()).getResolveHelper(); final CandidateInfo[] candidates = rh.getReferencedMethodCandidates(expr, true); final String text = expr.getText(); if (candidates.length > 0) { + if (candidates.length == 1) { + PsiElement element = candidates[0].getElement(); + if (element instanceof PsiMethod) return generateDoc(element, null); + } @NonNls final StringBuilder sb = new StringBuilder(); for (final CandidateInfo candidate : candidates) { diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java index 104546dd11e1..00d31a1f2dc7 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java @@ -26,6 +26,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.EffectiveLanguageLevelUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.DirectoryIndex; @@ -69,6 +70,8 @@ public class JavaPsiImplementationHelperImpl extends JavaPsiImplementationHelper public PsiClass getOriginalClass(PsiClass psiClass) { PsiCompiledElement cls = psiClass.getUserData(ClsElementImpl.COMPILED_ELEMENT); if (cls != null && cls.isValid()) return (PsiClass)cls; + + if (DumbService.isDumb(myProject)) return psiClass; VirtualFile vFile = psiClass.getContainingFile().getVirtualFile(); final ProjectFileIndex idx = ProjectRootManager.getInstance(myProject).getFileIndex(); diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java index a05b1dbd69e0..71b5f0366d05 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java @@ -44,10 +44,10 @@ public class ParameterData { myType = type; } - public static void createFromConstructor(final PsiMethod constructor, final Map result) { + public static void createFromConstructor(final PsiMethod constructor, String setterPrefix, final Map result) { for (PsiParameter parameter : constructor.getParameterList().getParameters()) { - initParameterData(parameter, result); + initParameterData(parameter, setterPrefix, result); } final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor); @@ -61,7 +61,7 @@ public class ParameterData { for (final PsiParameter parameter : chainedConstructor.getParameterList().getParameters()) { if (!parameter.isVarArgs()) { final PsiExpression arg = args[i]; - final ParameterData parameterData = initParameterData(parameter, result); + final ParameterData parameterData = initParameterData(parameter, setterPrefix, result); if (!(arg instanceof PsiReferenceExpression && ((PsiReferenceExpression)arg).resolve() instanceof PsiParameter)) { parameterData.setDefaultValue(arg.getText()); } @@ -71,7 +71,7 @@ public class ParameterData { } } - private static ParameterData initParameterData(PsiParameter parameter, Map result) { + private static ParameterData initParameterData(PsiParameter parameter, String setterPrefix, Map result) { JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(parameter.getProject()); final String paramName = parameter.getName(); final String pureParamName = styleManager.variableNameToPropertyName(paramName, VariableKind.PARAMETER); @@ -91,7 +91,7 @@ public class ParameterData { parameterData = new ParameterData(paramName, parameter.getType()); parameterData.setFieldName(styleManager.suggestVariableName(VariableKind.FIELD, uniqueParamName, null, parameter.getType()).names[0]); - parameterData.setSetterName(PropertyUtil.suggestSetterName(uniqueParamName)); + parameterData.setSetterName(PropertyUtil.suggestSetterName(uniqueParamName, setterPrefix)); result.put(uniqueParamName, parameterData); } diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java index 41cccd9453ee..f81aeca473ba 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java @@ -20,16 +20,24 @@ */ package com.intellij.refactoring.replaceConstructorWithBuilder; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.ide.util.TreeClassChooser; import com.intellij.ide.util.TreeClassChooserFactory; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidatorEx; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PropertyUtil; import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox; @@ -37,9 +45,10 @@ import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.ui.*; -import com.intellij.util.ui.Table; +import com.intellij.ui.table.JBTable; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -68,16 +77,20 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { private static final Logger LOG = Logger.getInstance("#" + ReplaceConstructorWithBuilderDialog.class.getName()); private final LinkedHashMap myParametersMap; private MyTableModel myTableModel; - private Table myTable; + private JBTable myTable; + private String mySetterPrefix; + private static final String RECENT_KEYS = "ReplaceConstructorWithBuilder.RECENT_KEYS"; + private static final String SETTER_PREFIX_KEY = "ConstructorWithBuilder.SetterPrefix"; protected ReplaceConstructorWithBuilderDialog(@NotNull Project project, PsiMethod[] constructors) { super(project, false); myConstructors = constructors; myParametersMap = new LinkedHashMap(); + mySetterPrefix = PropertiesComponent.getInstance(project).getValue(SETTER_PREFIX_KEY, "set"); for (PsiMethod constructor : constructors) { - ParameterData.createFromConstructor(constructor, myParametersMap); + ParameterData.createFromConstructor(constructor, mySetterPrefix, myParametersMap); } init(); setTitle(ReplaceConstructorWithBuilderProcessor.REFACTORING_NAME); @@ -109,6 +122,44 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { } + @Nullable + @Override + protected JComponent createNorthPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(new JLabel("Parameters to Pass to the Builder"), BorderLayout.CENTER); + + final DefaultActionGroup actionGroup = new DefaultActionGroup(null, false); + actionGroup.addAction(new AnAction("Rename Setters Prefix") { + @Override + public void actionPerformed(AnActionEvent e) { + applyNewSetterPrefix(); + } + }).setAsSecondary(true); + + panel.add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actionGroup, true).getComponent(), BorderLayout.EAST); + final Box box = Box.createHorizontalBox(); + box.add(panel); + box.add(Box.createHorizontalGlue()); + return box; + } + + private void applyNewSetterPrefix() { + final String setterPrefix = Messages.showInputDialog(myTable, "New setter prefix:", "Rename Setters Prefix", null, + mySetterPrefix, new MySetterPrefixInputValidator()); + if (setterPrefix != null) { + mySetterPrefix = setterPrefix; + PropertiesComponent.getInstance(myProject).setValue(SETTER_PREFIX_KEY, setterPrefix); + final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(myProject); + for (String paramName : myParametersMap.keySet()) { + final ParameterData data = myParametersMap.get(paramName); + paramName = data.getParamName(); + final String propertyName = javaCodeStyleManager.variableNameToPropertyName(paramName, VariableKind.PARAMETER); + data.setSetterName(PropertyUtil.suggestSetterName(propertyName, setterPrefix)); + } + myTable.revalidate(); + myTable.repaint(); + } + } protected JComponent createCenterPanel() { final Splitter splitter = new Splitter(true); @@ -171,7 +222,7 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { private JScrollPane createTablePanel() { myTableModel = new MyTableModel(); - myTable = new Table(myTableModel); + myTable = new JBTable(myTableModel); myTable.setSurrendersFocusOnKeystroke(true); myTable.getTableHeader().setReorderingAllowed(false); @@ -198,13 +249,7 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { myTable.setPreferredScrollableViewportSize(new Dimension(550, myTable.getRowHeight() * 12)); myTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); - //final Border titledBorder = IdeBorderFactory.createBoldTitledBorder("Parameters to Pass to the Builder"); - //final Border emptyBorder = BorderFactory.createEmptyBorder(0, 5, 5, 5); - //final Border border = BorderFactory.createCompoundBorder(titledBorder, emptyBorder); - //scrollPane.setBorder(border); - - return scrollPane; + return ScrollPaneFactory.createScrollPane(myTable); } private static final int PARAM = 0; @@ -338,4 +383,26 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { return null; } } + + private class MySetterPrefixInputValidator implements InputValidatorEx { + @Override + public boolean checkInput(String inputString) { + return getErrorText(inputString) == null; + } + + @Override + public boolean canClose(String inputString) { + return checkInput(inputString); + } + + @Nullable + @Override + public String getErrorText(String inputString) { + if (StringUtil.isEmpty(inputString)) { + return null; + } + return !PsiNameHelper.getInstance(myProject).isIdentifier(inputString) + ? "Identifier \'" + inputString + "\' is invalid" : null; + } + } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/VariableInIncompleteCodeSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/VariableInIncompleteCodeSearcher.java index abca8f160a3d..0c9800e6c70a 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/VariableInIncompleteCodeSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/VariableInIncompleteCodeSearcher.java @@ -37,13 +37,16 @@ public class VariableInIncompleteCodeSearcher extends QueryExecutorBase consumer) { final PsiElement refElement = p.getElementToSearch(); - if (!refElement.isValid() || !(refElement instanceof PsiLocalVariable || refElement instanceof PsiParameter)) return; + if (!refElement.isValid() || !(refElement instanceof PsiVariable)) return; final String name = ((PsiVariable)refElement).getName(); if (name == null) return; - final SearchScope scope = p.getEffectiveSearchScope(); - if (!(scope instanceof LocalSearchScope)) return; + SearchScope scope = p.getEffectiveSearchScope(); + if (!(scope instanceof LocalSearchScope)) { + //process incomplete references to the 'field' in the same file only + scope = new LocalSearchScope(refElement.getContainingFile()); + } PsiElement[] elements = ((LocalSearchScope)scope).getScope(); if (elements.length == 0) return; diff --git a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java index 85b5cf1b6e42..b33600944ffa 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java @@ -101,33 +101,31 @@ public abstract class PsiElementFinder { } /** - * Returns a list of children (classes, subpackages and possibly other elements) belonging to the specified package. + * Returns a list of files belonging to the specified package which are not located in any of the package directories. * - * @param psiPackage the package to return the list of children for. - * @param scope the scope in which children are searched. - * @return the list of children. + * @param psiPackage the package to return the list of files for. + * @param scope the scope in which files are searched. + * @return the list of files. * @since 14.1 */ @NotNull - public PsiNamedElement[] getChildren(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { - Set children = new HashSet(); - Collections.addAll(children, getSubPackages(psiPackage, scope)); - Collections.addAll(children, getClasses(psiPackage, scope)); - return children.toArray(new PsiNamedElement[children.size()]); + public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + return PsiFile.EMPTY_ARRAY; } /** - * Returns the filter to use for filtering the list of children for a given package produced by other PsiElementFinder - * implementations. (For example, the list of children for a Kotlin package includes files directly, rather than classes, - * so the classes located by the standard Java package children finder need to be excluded.) + * Returns the filter to use for filtering the list of files in the directories belonging to a package to exclude files + * that actually belong to a different package. (For example, in Kotlin the package of a file is determined by its + * package statement and not by its location in the directory structure, so the files which have a differring package + * statement need to be excluded.) * - * @param psiPackage the package to return the list of children for. - * @param scope the scope in which children are searched. + * @param psiPackage the package for which the list of files is requested. + * @param scope the scope in which children are requested. * @return the filter to use, or null if no additional filtering is necessary. * @since 14.1 */ @Nullable - public Predicate getPackageChildrenFilter(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + public Predicate getPackageFilesFilter(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { return null; } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java index cab1728ad650..1a3db4d1301b 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java @@ -84,12 +84,13 @@ public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, Psi PsiClass[] getClasses(@NotNull GlobalSearchScope scope); /** - * Returns the list of all elements (classes, subpackages and potentially other elements) belonging to this package - * (non-recursively), restricted by the specified scope. + * Returns the list of all files in the package, restricted by the specified scope. (This is + * normally the list of all files in all directories corresponding to the package, but it can + * be modified by custom language plugins which have a different notion of packages.) * * @since 14.1 */ - PsiElement[] getChildren(@NotNull GlobalSearchScope scope); + PsiFile[] getFiles(@NotNull GlobalSearchScope scope); /** * Returns the list of package-level annotations for the package. diff --git a/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java index 4b7de701c325..7c1f7ac70732 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java @@ -345,9 +345,16 @@ public class PropertyUtil { } public static String suggestSetterName(@NonNls String propertyName) { - @NonNls StringBuilder name = - new StringBuilder(StringUtil.capitalizeWithJavaBeanConvention(StringUtil.sanitizeJavaIdentifier(propertyName))); - name.insert(0, "set"); + return suggestSetterName(propertyName, "set"); + } + + public static String suggestSetterName(@NonNls String propertyName, String setterPrefix) { + final String sanitizeJavaIdentifier = StringUtil.sanitizeJavaIdentifier(propertyName); + if (StringUtil.isEmpty(setterPrefix)) { + return sanitizeJavaIdentifier; + } + @NonNls StringBuilder name = new StringBuilder(StringUtil.capitalizeWithJavaBeanConvention(sanitizeJavaIdentifier)); + name.insert(0, setterPrefix); return name.toString(); } diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 1c023d6f1797..f30ad7c999d6 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -585,11 +585,26 @@ public class JavaDocInfoGenerator { public void generateCommonSection(StringBuilder buffer, PsiDocComment docComment) { generateDescription(buffer, docComment); + generateApiSection(buffer, docComment); generateDeprecatedSection(buffer, docComment); generateSinceSection(buffer, docComment); generateSeeAlsoSection(buffer, docComment); } + private void generateApiSection(StringBuilder buffer, PsiDocComment comment) { + final String[] tagNames = {"apiNote", "implSpec", "implNote"}; + for (String tagName : tagNames) { + PsiDocTag tag = comment.findTagByName(tagName); + if (tag != null) { + buffer.append("
"); + buffer.append("
").append(tagName).append(""); + buffer.append("
"); + generateValue(buffer, tag.getDataElements(), ourEmptyElementsProvider); + buffer.append("
"); + } + } + } + private void generatePackageHtmlJavaDoc(final StringBuilder buffer, final PsiFile packageHtmlFile, boolean generatePrologueAndEpilogue) { String htmlText = packageHtmlFile.getText(); @@ -912,6 +927,7 @@ public class JavaDocInfoGenerator { generateThrowsSection(buffer, method, comment); if (comment != null) { + generateApiSection(buffer, comment); generateSinceSection(buffer, comment); generateSeeAlsoSection(buffer, comment); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index 028e067666fc..a99550bad82c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -243,17 +243,17 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); } - private static class AndPredicate implements Predicate { - private final List> myComponents = new SmartList>(); + private static class AndPredicate implements Predicate { + private final List> myComponents = new SmartList>(); - public AndPredicate(Predicate filter1, Predicate filter2) { + public AndPredicate(Predicate filter1, Predicate filter2) { myComponents.add(filter1); myComponents.add(filter2); } @Override - public boolean apply(@Nullable PsiNamedElement input) { - for (Predicate component : myComponents) { + public boolean apply(@Nullable T input) { + for (Predicate component : myComponents) { if (!component.apply(input)) { return false; } @@ -263,34 +263,38 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { } @NotNull - public PsiElement[] getPackageChildren(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { - Map result = new HashMap(); - Predicate filter = null; + public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + Predicate filter = null; for (PsiElementFinder finder : filteredFinders()) { - Predicate finderFilter = finder.getPackageChildrenFilter(psiPackage, scope); + Predicate finderFilter = finder.getPackageFilesFilter(psiPackage, scope); if (finderFilter != null) { if (filter == null) { filter = finderFilter; } else if (filter instanceof AndPredicate) { - ((AndPredicate) filter).myComponents.add(finderFilter); + ((AndPredicate) filter).myComponents.add(finderFilter); } else { - filter = new AndPredicate(filter, finderFilter); + filter = new AndPredicate(filter, finderFilter); + } + } + } + + Set result = new HashSet(); + PsiDirectory[] directories = psiPackage.getDirectories(scope); + for (PsiDirectory directory : directories) { + for (PsiFile file : directory.getFiles()) { + if (filter == null || filter.apply(file)) { + result.add(file); } } } for (PsiElementFinder finder : filteredFinders()) { - PsiNamedElement[] children = finder.getChildren(psiPackage, scope); - for (PsiNamedElement child : children) { - if (!result.containsKey(child.getName()) && (filter == null || filter.apply(child))) { - result.put(child.getName(), child); - } - } + Collections.addAll(result, finder.getPackageFiles(psiPackage, scope)); } - return result.values().toArray(new PsiElement[result.size()]); + return result.toArray(new PsiFile[result.size()]); } public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 7e12adac007d..c410b37dcb91 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -23,7 +23,6 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; -import com.intellij.psi.filters.OrFilter; import com.intellij.psi.impl.source.ClassInnerStuffCache; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; @@ -45,6 +44,7 @@ import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.NullableFunction; import com.intellij.util.SmartList; +import com.intellij.util.containers.ConcurrentFactoryMap; import com.intellij.util.containers.HashSet; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -214,54 +214,6 @@ public class PsiClassImplUtil { public enum MemberType {CLASS, FIELD, METHOD} - @NotNull - private static MembersMap buildAllMaps(@NotNull PsiClass psiClass) { - final List> classes = new ArrayList>(); - final List> fields = new ArrayList>(); - final List> methods = new ArrayList>(); - - FilterScopeProcessor processor = new FilterScopeProcessor( - new OrFilter(ElementClassFilter.METHOD, ElementClassFilter.FIELD, ElementClassFilter.CLASS)) { - @Override - protected void add(@NotNull PsiElement element, @NotNull PsiSubstitutor substitutor) { - if (element instanceof PsiMethod) { - methods.add(Pair.create((PsiMember)element, substitutor)); - } - else if (element instanceof PsiField) { - fields.add(Pair.create((PsiMember)element, substitutor)); - } - else if (element instanceof PsiClass) { - classes.add(Pair.create((PsiMember)element, substitutor)); - } - } - }; - processDeclarationsInClassNotCached(psiClass, processor, ResolveState.initial(), null, null, psiClass, false, - PsiUtil.getLanguageLevel(psiClass)); - - MembersMap result = new MembersMap(MemberType.class); - result.put(MemberType.CLASS, generateMapByList(classes)); - result.put(MemberType.METHOD, generateMapByList(methods)); - result.put(MemberType.FIELD, generateMapByList(fields)); - return result; - } - - @NotNull - private static Map>> generateMapByList(@NotNull final List> list) { - Map>> map = new THashMap>>(); - map.put(ALL, list); - for (final Pair info : list) { - PsiMember element = info.getFirst(); - String currentName = element.getName(); - List> listByName = map.get(currentName); - if (listByName == null) { - listByName = new ArrayList>(1); - map.put(currentName, listByName); - } - listByName.add(info); - } - return map; - } - private static Map>> getMap(@NotNull PsiClass aClass, @NotNull MemberType type) { ParameterizedCachedValue value = getValues(aClass); return value.getValue(aClass).get(type); @@ -407,9 +359,46 @@ public class PsiClassImplUtil { return factory.createMethodFromText(text, null).getSignature(PsiSubstitutor.EMPTY); } - private static class MembersMap extends EnumMap>>> { - public MembersMap(@NotNull Class keyType) { - super(keyType); + private static class MembersMap extends ConcurrentFactoryMap>>> { + private final PsiClass myPsiClass; + + public MembersMap(PsiClass psiClass) { + myPsiClass = psiClass; + } + + @Nullable + @Override + protected Map>> create(final MemberType key) { + final Map>> map = new THashMap>>(); + + final List> allMembers = new ArrayList>(); + map.put(ALL, allMembers); + + ElementClassFilter filter = key == MemberType.CLASS ? ElementClassFilter.CLASS : + key == MemberType.METHOD ? ElementClassFilter.METHOD : + ElementClassFilter.FIELD; + FilterScopeProcessor processor = new FilterScopeProcessor(filter) { + @Override + protected void add(@NotNull PsiElement element, @NotNull PsiSubstitutor substitutor) { + if (key == MemberType.CLASS && element instanceof PsiClass || + key == MemberType.METHOD && element instanceof PsiMethod || + key == MemberType.FIELD && element instanceof PsiField) { + Pair info = Pair.create((PsiMember)element, substitutor); + allMembers.add(info); + String currentName = ((PsiMember)element).getName(); + List> listByName = map.get(currentName); + if (listByName == null) { + listByName = new ArrayList>(1); + map.put(currentName, listByName); + } + listByName.add(info); + } + } + }; + + processDeclarationsInClassNotCached(myPsiClass, processor, ResolveState.initial(), null, null, myPsiClass, false, + PsiUtil.getLanguageLevel(myPsiClass)); + return map; } } @@ -418,8 +407,7 @@ public class PsiClassImplUtil { @Override public CachedValueProvider.Result compute(@NotNull PsiClass myClass) { - MembersMap map = buildAllMaps(myClass); - return new CachedValueProvider.Result(map, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); + return new CachedValueProvider.Result(new MembersMap(myClass), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index d1b0a3553a13..1915df3b09c8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java @@ -20,6 +20,8 @@ import com.intellij.lang.Language; import com.intellij.lang.java.JavaLanguage; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentationProviders; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.util.Condition; @@ -46,6 +48,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Queryable { + private static final Logger LOG = Logger.getInstance(PsiPackageImpl.class); + private volatile CachedValue myAnnotationList; private volatile CachedValue> myDirectories; private volatile CachedValue> myDirectoriesWithLibSources; @@ -153,15 +157,9 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya return getFacade().getClasses(this, scope); } - @NotNull @Override - public PsiElement[] getChildren() { - return getChildren(allScope()); - } - - @Override - public PsiElement[] getChildren(@NotNull GlobalSearchScope scope) { - return getFacade().getPackageChildren(this, scope); + public PsiFile[] getFiles(@NotNull GlobalSearchScope scope) { + return getFacade().getPackageFiles(this, scope); } @Override @@ -321,7 +319,17 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya @NotNull Condition nameCondition) { for (PsiClass aClass : classes) { String name = aClass.getName(); - if (name != null && nameCondition.value(name) && !processor.execute(aClass, state)) return false; + if (name != null && nameCondition.value(name)) { + try { + if (!processor.execute(aClass, state)) return false; + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Exception e) { + LOG.error(e); + } + } } return true; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java index 9b4be9c071c9..882e6b68498f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java @@ -44,6 +44,9 @@ public class JavadocManagerImpl implements JavadocManager { myInfos.add(new SimpleDocTagInfo("serialField", PsiField.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("since", PsiElement.class, PsiPackage.class, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("version", PsiClass.class, PsiPackage.class, LanguageLevel.JDK_1_3)); + myInfos.add(new SimpleDocTagInfo("apiNote", PsiElement.class, false, LanguageLevel.JDK_1_8)); + myInfos.add(new SimpleDocTagInfo("implNote", PsiElement.class, false, LanguageLevel.JDK_1_8)); + myInfos.add(new SimpleDocTagInfo("implSpec", PsiElement.class, false, LanguageLevel.JDK_1_8)); myInfos.add(new SimpleDocTagInfo("docRoot", PsiElement.class, true, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("inheritDoc", PsiElement.class, true, LanguageLevel.JDK_1_4)); diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java new file mode 100644 index 000000000000..e33d32fd1c1b --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java @@ -0,0 +1,10 @@ +public class Main { + + + public int a = 3; + protected Object obj = null; + private long e = 4; + + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_before.java new file mode 100644 index 000000000000..c65c426808e3 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_before.java @@ -0,0 +1,17 @@ +import java.lang.Object; +import java.util.LinkedHashSet; +import java.util.Set; + +public class Main { + + + + public int a = 3; +private long e = 4; + + + protected Object obj = null; + + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_revision.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_revision.java new file mode 100644 index 000000000000..c922c3a0fff4 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_revision.java @@ -0,0 +1,10 @@ +import java.util.LinkedHashSet; +import java.util.Set; + +public class Main { + + + + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeWholeFile_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeWholeFile_after.java new file mode 100644 index 000000000000..325157e34237 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeWholeFile_after.java @@ -0,0 +1,15 @@ +import java.util.List; + +public class Test { + + public long newRun; + public int ab; + public int awe; + private int c; + + public void run() { + List strings = null; + } + + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeWholeFile_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeWholeFile_before.java new file mode 100644 index 000000000000..40f2bdf8a1cd --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeWholeFile_before.java @@ -0,0 +1,21 @@ +import java.util.HashMap; +import java.util.Set; +import java.util.List; + +public class Test { + + public long newRun; + + public void run() { + List strings = null; + } + + public int ab; + private int c; + + + public int awe; + + + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_after.java new file mode 100644 index 000000000000..d8b472a1ec80 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_after.java @@ -0,0 +1,23 @@ +import java.util.LinkedHashSet; +import java.util.Set; + +public class Main { + + + public static void main(String[] args) { + Runnable runnable = new Runnable() { + @Override + public void run() { + Set test = new LinkedHashSet(); + if (test.contains("AA")) { + if (test.contains("AS")) { + System.out.println("AAAA!"); + } + } + } + }; + + runnable.run(); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_before.java new file mode 100644 index 000000000000..8d972e12b704 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_before.java @@ -0,0 +1,27 @@ +import java.lang.Override; +import java.lang.Runnable; +import java.lang.String; +import java.util.Set; +import java.util.HashSet; +import java.util.LinkedHashSet; + +public class Main { + + + public static void main(String[] args) { + Runnable runnable = new Runnable() { + @Override + public void run() { + Set test = new LinkedHashSet(); + if (test.contains("AA")) { + if (test.contains("AS")) { + System.out.println("AAAA!"); + } + } + } + }; + + runnable.run(); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_revision.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_revision.java new file mode 100644 index 000000000000..0818983f8e7d --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeVcsChanges_revision.java @@ -0,0 +1,23 @@ +import com.intellij.util.containers.HashSet; + +import java.util.Set; +import java.util.HashSet; + +public class Main { + + + public static void main(String[] args) { + Runnable runnable = new Runnable() { + @Override + public void run() { + Set test = new HashSet(); + if (test.contains("AA")) { + System.out.println("AAAA!"); + } + } + }; + + runnable.run(); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeWholeFile_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeWholeFile_after.java new file mode 100644 index 000000000000..1a0c071acd66 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeWholeFile_after.java @@ -0,0 +1,10 @@ +import java.util.List; + +public class Test { + + + public void run() { + List strings = null; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeWholeFile_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeWholeFile_before.java new file mode 100644 index 000000000000..26f115f2588b --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeWholeFile_before.java @@ -0,0 +1,12 @@ +import java.util.HashMap; +import java.util.Set; +import java.util.List; + +public class Test { + + + public void run() { + List strings = null; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatRearrangeSelection_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatRearrangeSelection_after.java new file mode 100644 index 000000000000..fb22c27cefc8 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatRearrangeSelection_after.java @@ -0,0 +1,9 @@ +class Test { + + public int a = 3; + private int b = 3; + + +public void run () {} +int aero = 12; +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatRearrangeSelection_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatRearrangeSelection_before.java new file mode 100644 index 000000000000..0f1201c936ea --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatRearrangeSelection_before.java @@ -0,0 +1,9 @@ +class Test { + + private int b = 3; +public int a = 3; + + +public void run () {} +int aero = 12; +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_after.java new file mode 100644 index 000000000000..357b4779dc09 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_after.java @@ -0,0 +1,15 @@ +public class Test { + + int a = 3; + + int c = 12; + + public void run() { + + int arr = 12; + long test = 1; + + } + + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_before.java new file mode 100644 index 000000000000..c28ea3ea10db --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_before.java @@ -0,0 +1,15 @@ +public class Test { + + int a = 3; + + int c = 12; + + public void run() { + + int arr = 12; +long test =1; + + } + + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_after.java new file mode 100644 index 000000000000..17cc8ec1273f --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_after.java @@ -0,0 +1,13 @@ +public class Test { + +public void run() { + + int a = 3; + int b = 12; + +} + + public void test() { + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_before.java new file mode 100644 index 000000000000..5a92198fefee --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_before.java @@ -0,0 +1,13 @@ +public class Test { + +public void run() { + +int a = 3; +int b = 12; + +} + +public void test() { +} + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_revision.java b/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_revision.java new file mode 100644 index 000000000000..c7c76f24f5a0 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatVcsChanges_revision.java @@ -0,0 +1,10 @@ +public class Test { + +public void run() { + + int a = 3; + +} + + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatWholeFile_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatWholeFile_after.java new file mode 100644 index 000000000000..837621dd5421 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatWholeFile_after.java @@ -0,0 +1,8 @@ +public class Test { + + int a = 3; + + + void run() { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatWholeFile_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatWholeFile_before.java new file mode 100644 index 000000000000..d20b5115dd61 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatWholeFile_before.java @@ -0,0 +1,9 @@ +public class Test { + + int a = 3; + + +void run() +{ +} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/className/docAfterNew/before1.java b/java/java-tests/testData/codeInsight/completion/className/docAfterNew/before1.java new file mode 100644 index 000000000000..bc4587d40766 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/className/docAfterNew/before1.java @@ -0,0 +1,5 @@ +public class Test1 { + public void foo() { + new Tim + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java new file mode 100644 index 000000000000..80a6789e8f50 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java @@ -0,0 +1,8 @@ +class Test { + /** + * @apiNote note1 + * @implNote implNote + * @implSpec implSpec + */ + public void i() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/generateEquals/afterArraysFromJava15.java b/java/java-tests/testData/codeInsight/generateEquals/afterArraysFromJava15.java index cc5a036a3e24..801e8eaa4b7f 100644 --- a/java/java-tests/testData/codeInsight/generateEquals/afterArraysFromJava15.java +++ b/java/java-tests/testData/codeInsight/generateEquals/afterArraysFromJava15.java @@ -11,7 +11,7 @@ class Test { final Test test = (Test) o; - // Compare nested arrays - values of myIIs here + if (!Arrays.deepEquals(myIIs, test.myIIs)) return false; if (!Arrays.equals(myIs, test.myIs)) return false; // Probably incorrect - comparing Object[] arrays with Arrays.equals if (!Arrays.equals(myOs, test.myOs)) return false; @@ -21,7 +21,8 @@ class Test { public int hashCode() { int result = myOs != null ? Arrays.hashCode(myOs) : 0; - result = 31 * result + (myIIs != null ? Arrays.hashCode(myIIs) : 0); + result = 31 * result + (myIIs != null ? // Probably incorrect - hashCode for high dimension arrays with Arrays.hashCode + Arrays.hashCode(myIIs) : 0); result = 31 * result + (myIs != null ? Arrays.hashCode(myIs) : 0); return result; } diff --git a/java/java-tests/testData/codeInsight/javadocIG/apiNotes.html b/java/java-tests/testData/codeInsight/javadocIG/apiNotes.html new file mode 100644 index 000000000000..b731e4ecefcc --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/apiNotes.html @@ -0,0 +1 @@ + Test
public void foo()
apiNote
my api note
implSpec
my impl spec
implNote
my impl note
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/apiNotes.java b/java/java-tests/testData/codeInsight/javadocIG/apiNotes.java new file mode 100644 index 000000000000..a0227cfd597e --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/apiNotes.java @@ -0,0 +1,13 @@ +class Test { + /** + * @apiNote + * my api note + * + * @implSpec + * my impl spec + * + * @implNote + * my impl note + */ + public void foo(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/list/TemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription.java b/java/java-tests/testData/codeInsight/template/list/TemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription.java new file mode 100644 index 000000000000..cc169cd51364 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/list/TemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription.java @@ -0,0 +1,5 @@ +class A { + public static void main() { + template.with.desc + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/list/TemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription_after.java b/java/java-tests/testData/codeInsight/template/list/TemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription_after.java new file mode 100644 index 000000000000..b0424f42172d --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/list/TemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription_after.java @@ -0,0 +1,5 @@ +class A { + public static void main() { + template with description + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/renameInplace/RenameFieldInIncompleteStatement.java b/java/java-tests/testData/refactoring/renameInplace/RenameFieldInIncompleteStatement.java new file mode 100644 index 000000000000..c8d93d0992fd --- /dev/null +++ b/java/java-tests/testData/refactoring/renameInplace/RenameFieldInIncompleteStatement.java @@ -0,0 +1,11 @@ +class MyTest { + + String foo; + + { + I i; + + foo + i = MyTest::foo; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/renameInplace/RenameFieldInIncompleteStatement_after.java b/java/java-tests/testData/refactoring/renameInplace/RenameFieldInIncompleteStatement_after.java new file mode 100644 index 000000000000..6ce66c6224a4 --- /dev/null +++ b/java/java-tests/testData/refactoring/renameInplace/RenameFieldInIncompleteStatement_after.java @@ -0,0 +1,11 @@ +class MyTest { + + String bar; + + { + I i; + + bar + i = MyTest::foo; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy index 426dd9f5dc68..306367f6994b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy @@ -14,15 +14,70 @@ * limitations under the License. */ package com.intellij.codeInsight - +import com.intellij.codeInsight.documentation.DocumentationManager import com.intellij.codeInsight.navigation.CtrlMouseHandler +import com.intellij.lang.java.JavaDocumentationProvider +import com.intellij.psi.PsiExpressionList +import com.intellij.psi.util.PsiTreeUtil import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase - /** * @author peter */ class JavaDocumentationTest extends LightCodeInsightFixtureTestCase { + public void testConstructorDoc() { + myFixture.configureByText 'a.java', ''' +class Foo { Foo() {} Foo(int param) {} } + +class Foo2 {{ + new Foo +}} +''' + def originalElement = myFixture.file.findElementAt(myFixture.editor.caretModel.offset) + def doc = new JavaDocumentationProvider().generateDoc( + DocumentationManager.getInstance(project).findTargetElement(myFixture.editor, myFixture.file), + originalElement + ) + + assert doc == """Candidates for new Foo() are:
  Foo()
  Foo(int param)
""" + } + + public void testConstructorDoc2() { + myFixture.configureByText 'a.java', ''' +class Foo { Foo() {} Foo(int param) {} } + +class Foo2 {{ + new Foo() +}} +''' + + def elementAt = myFixture.file.findElementAt(myFixture.editor.caretModel.offset) + def exprList = PsiTreeUtil.getParentOfType(elementAt, PsiExpressionList.class) + def doc = new JavaDocumentationProvider().generateDoc( + exprList, + elementAt + ) + + assert doc == """Candidates for new Foo() are:
  Foo()
  Foo(int param)
""" + } + + public void testMethodDocWhenInArgList() { + myFixture.configureByText 'a.java', ''' +class Foo { void doFoo() {} } + +class Foo2 {{ + new Foo().doFoo() +}} +''' + def exprList = PsiTreeUtil.getParentOfType(myFixture.file.findElementAt(myFixture.editor.caretModel.offset), PsiExpressionList.class) + def doc = new JavaDocumentationProvider().generateDoc( + exprList, + null + ) + + assert doc == """ Foo
void doFoo()
""" + } + public void testGenericMethod() { myFixture.configureByText 'a.java', ''' class Bar { java.util.List foo(T param); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java index abf7f3880c9c..929c1463b979 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java @@ -28,7 +28,6 @@ import com.intellij.testFramework.LightCodeInsightTestCase; import com.intellij.testFramework.utils.parameterInfo.MockCreateParameterInfoContext; import com.intellij.testFramework.utils.parameterInfo.MockParameterInfoUIContext; import com.intellij.testFramework.utils.parameterInfo.MockUpdateParameterInfoContext; -import com.intellij.util.ArrayUtilRt; import com.intellij.util.Function; import junit.framework.Assert; @@ -104,21 +103,10 @@ public class ParameterInfoTest extends LightCodeInsightTestCase { assertEquals(2, itemsToShow.length); assertTrue(itemsToShow[0] instanceof MethodCandidateInfo); final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, -1); - final Boolean [] enabled = new Boolean[itemsToShow.length]; - final MockUpdateParameterInfoContext updateParameterInfoContext = new MockUpdateParameterInfoContext(myEditor, myFile){ - @Override - public Object[] getObjectsToView() { - return itemsToShow; - } - - @Override - public void setUIComponentEnabled(int index, boolean b) { - enabled[index] = b; - } - }; + final MockUpdateParameterInfoContext updateParameterInfoContext = new MockUpdateParameterInfoContext(myEditor, myFile, itemsToShow); updateParameterInfoContext.setParameterOwner(list); handler.updateParameterInfo(list, updateParameterInfoContext); - assertTrue(ArrayUtilRt.find(enabled, Boolean.TRUE) > -1); + assertTrue(updateParameterInfoContext.isUIComponentEnabled(0) || updateParameterInfoContext.isUIComponentEnabled(1)); } public void testAfterGenericsInsideCall() throws Exception { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java new file mode 100644 index 000000000000..0dd2bcebc27d --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ReformatCodeActionInEditorTest extends LightCodeInsightFixtureTestCase { + + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath() + "/actions/reformatFileInEditor/"; + } + + public void doTest(@NotNull ReformatFilesOptions options) { + setOptions(options); + + String before = null; + if (options.isProcessOnlyChangedText()) { + myFixture.configureByFile(getTestName(true) + "_revision.java"); + PsiFile file = myFixture.getFile(); + Document document = myFixture.getDocument(file); + before = document.getText(); + } + + myFixture.configureByFile(getTestName(true) + "_before.java"); + + if (before != null) { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, before); + } + + final String actionId = IdeActions.ACTION_EDITOR_REFORMAT; + AnAction action = ActionManager.getInstance().getAction(actionId); + + AnActionEvent event = createEventFor(action, getProject(), myFixture.getEditor()); + + action.actionPerformed(event); + myFixture.checkResultByFile(getTestName(true) + "_after.java"); + } + + @Override + public void tearDown() throws Exception { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); + super.tearDown(); + } + + protected AnActionEvent createEventFor(@NotNull AnAction action, @NotNull final Project project, @NotNull final Editor editor) { + return new AnActionEvent(null, new DataContext() { + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (CommonDataKeys.PROJECT.is(dataId)) return project; + if (CommonDataKeys.EDITOR.is(dataId)) return editor; + return null; + } + }, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0); + } + + protected void setOptions(ReformatFilesOptions options) { + ReformatCodeAction.setTestOptions(options); + } + + public void testFormatWholeFile() { + doTest(new MockReformatFileSettings().setProcessWholeFile(true)); + } + + public void testFormatOptimizeWholeFile() { + doTest(new MockReformatFileSettings().setProcessWholeFile(true).setOptimizeImports(true)); + } + + public void testFormatOptimizeRearrangeWholeFile() { + doTest(new MockReformatFileSettings().setProcessWholeFile(true).setOptimizeImports(true).setRearrange(true)); + } + + public void testFormatSelection() { + doTest(new MockReformatFileSettings().setProcessWholeFile(false)); + } + + public void testFormatRearrangeSelection() { + doTest(new MockReformatFileSettings().setProcessWholeFile(false).setRearrange(true)); + } + + public void testFormatVcsChanges() { + doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true)); + } + + public void testFormatOptimizeVcsChanges() { + doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true).setOptimizeImports(true)); + } + + public void testFormatOptimizeRearrangeVcsChanges() { + doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true).setOptimizeImports(true).setRearrange(true)); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java index 03310a87bb38..55772a467963 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java @@ -19,11 +19,13 @@ import com.intellij.JavaTestUtil; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.lang.java.JavaDocumentationProvider; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.PsiClass; import com.intellij.testFramework.TestDataPath; import java.io.IOException; @@ -58,6 +60,23 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase { checkResultByFile(path + "/after2.java"); } + public void testDocAfterNew() throws Exception { + createClass("public class Time { Time() {} Time(long time) {} }"); + + String path = "/docAfterNew"; + + configureByFile(path + "/before1.java"); + assertTrue(myItems != null && myItems.length >= 1); + String doc = new JavaDocumentationProvider().generateDoc( + (PsiClass)myItems[0].getObject(), + myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()) + ); + + assertEquals(doc, + "Candidates for new Time() are:
  Time()
 " + + " Time(long time)
"); + } + public void testTypeParametersTemplate() throws Exception { createClass("package pack; public interface Foo {void foo(T t};"); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java index 52c201d3cb54..ef47e405467a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java @@ -95,6 +95,7 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { public void testValueNotOnField() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } public void testValueNotOnStaticField() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } public void testValueOnNotInitializedField() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } + public void testJava18Tags() throws Exception { doTestWithLangLevel(LanguageLevel.JDK_1_8); } public void testUnknownInlineTag() throws Exception { doTest(); } public void testUnknownTags() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java index bb132e19fd08..ef891b913836 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -113,6 +113,10 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase { doTestMethod(); } + public void testApiNotes() throws Exception { + doTestMethod(); + } + public void testLiteral() throws Exception { doTestField(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/ListTemplateActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/ListTemplateActionTest.java index 6c06350b059d..6b24f902a613 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/template/ListTemplateActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/ListTemplateActionTest.java @@ -33,6 +33,7 @@ public class ListTemplateActionTest extends LightCodeInsightFixtureTestCase { TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable()); addTemplate("simple", "simple template text", "description"); addTemplate("complex key", "complex template text", ""); + addTemplate("template.with.desc", "template with description", "desc"); } private void addTemplate(String key, String text, String description) { @@ -92,6 +93,10 @@ public class ListTemplateActionTest extends LightCodeInsightFixtureTestCase { public void testComplexKeyWithNotMatchedPrefixAfterNonJavaCharacter() { doTest("complex key"); } + + public void testTemplateShouldNotBeReplacedByOtherTemplateMatchedByDescription() { + doTest("template.with.desc"); + } private void doTest(@NotNull String lookupText) { myFixture.configureByFile(getTestName(false) + ".java"); diff --git a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java index b26afb406d5b..c27aa2c38052 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java @@ -115,7 +115,7 @@ public class NavigateFromSourceTest extends BaseProjectViewTestCase { pane.select(psiClass, psiClass.getContainingFile().getVirtualFile(), true); - assertEquals(9, tree.getSelectionCount()); + assertEquals(8, tree.getSelectionCount()); } private static void changeClassTextAndTryToNavigate(final String newClassString, diff --git a/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java new file mode 100644 index 000000000000..74c0a402d9fc --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * Neither the name of JetBrains or IntelliJ IDEA + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT + * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT + * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN + * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ +package com.intellij.projectView; + +import com.intellij.ide.projectView.ProjectView; +import com.intellij.ide.projectView.impl.AbstractProjectTreeStructure; +import com.intellij.ide.projectView.impl.PackageViewPane; +import com.intellij.ide.projectView.impl.ProjectViewImpl; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.impl.ModuleManagerImpl; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.TestSourceBasedTestCase; +import com.intellij.util.ui.tree.TreeUtil; +import com.intellij.lang.properties.projectView.ResourceBundleGrouper; +import org.jetbrains.annotations.NonNls; + +import javax.swing.*; +import java.io.IOException; + +public class PackagesTreeStructureTest extends TestSourceBasedTestCase { + public void testPackageView() throws IOException { + ModuleManagerImpl.getInstanceImpl(myProject).setModuleGroupPath(myModule, new String[]{"Group"}); + final VirtualFile srcFile = getSrcDirectory().getVirtualFile(); + if (srcFile.findChild("empty") == null){ + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + try { + srcFile.createChildDirectory(this, "empty"); + } + catch (IOException e) { + fail(e.getLocalizedMessage()); + } + } + }); + } + + doTest(true, true, "-Project\n" + + " -Group: Group\n" + + " -Module\n" + + " -PsiPackage: com.package1\n" + + " Class1.java\n" + + " Class2.java\n" + + " Class4.java\n" + + " Form1.form\n" + + " Form1.java\n" + + " Form2.form\n" + + " PsiPackage: empty\n" + + " -PsiPackage: java\n" + + " Class1.java\n" + + " -PsiPackage: javax.servlet\n" + + " Class1.java\n" + + " -Libraries\n" + + " -PsiPackage: java\n" + + " +PsiPackage: awt\n" + + " +PsiPackage: beans.beancontext\n" + + " +PsiPackage: io\n" + + " +PsiPackage: lang\n" + + " +PsiPackage: net\n" + + " +PsiPackage: rmi\n" + + " +PsiPackage: security\n" + + " +PsiPackage: sql\n" + + " +PsiPackage: util\n" + + " -PsiPackage: javax.swing\n" + + " +PsiPackage: table\n" + + " AbstractButton.class\n" + + " Icon.class\n" + + " JButton.class\n" + + " JComponent.class\n" + + " JDialog.class\n" + + " JFrame.class\n" + + " JLabel.class\n" + + " JPanel.class\n" + + " JScrollPane.class\n" + + " JTable.class\n" + + " SwingConstants.class\n" + + " SwingUtilities.class\n" + + " -PsiPackage: META-INF\n" + + " MANIFEST.MF\n" + + " MANIFEST.MF\n" + + " -PsiPackage: org\n" + + " +PsiPackage: intellij.lang.annotations\n" + + " +PsiPackage: jetbrains.annotations\n" + + "" + , 5); + + doTest(false, true, "-Project\n" + + " -PsiPackage: com.package1\n" + + " Class1.java\n" + + " Class2.java\n" + + " Class4.java\n" + + " Form1.form\n" + + " Form1.java\n" + + " Form2.form\n" + + " PsiPackage: empty\n" + + " -PsiPackage: java\n" + + " Class1.java\n" + + " -PsiPackage: javax.servlet\n" + + " Class1.java\n" + + " -Libraries\n" + + " -PsiPackage: java\n" + + " +PsiPackage: awt\n" + + " +PsiPackage: beans.beancontext\n" + + " +PsiPackage: io\n" + + " +PsiPackage: lang\n" + + " +PsiPackage: net\n" + + " +PsiPackage: rmi\n" + + " +PsiPackage: security\n" + + " +PsiPackage: sql\n" + + " +PsiPackage: util\n" + + " -PsiPackage: javax.swing\n" + + " +PsiPackage: table\n" + + " AbstractButton.class\n" + + " Icon.class\n" + + " JButton.class\n" + + " JComponent.class\n" + + " JDialog.class\n" + + " JFrame.class\n" + + " JLabel.class\n" + + " JPanel.class\n" + + " JScrollPane.class\n" + + " JTable.class\n" + + " SwingConstants.class\n" + + " SwingUtilities.class\n" + + " -PsiPackage: META-INF\n" + + " MANIFEST.MF\n" + + " MANIFEST.MF\n" + + " -PsiPackage: org\n" + + " +PsiPackage: intellij.lang.annotations\n" + + " +PsiPackage: jetbrains.annotations\n" + , 3); + + doTest(true, false, "-Project\n" + + " -Group: Group\n" + + " -Module\n" + + " -PsiPackage: com.package1\n" + + " Class1.java\n" + + " Class2.java\n" + + " Class4.java\n" + + " Form1.form\n" + + " Form1.java\n" + + " Form2.form\n" + + " PsiPackage: empty\n" + + " -PsiPackage: java\n" + + " Class1.java\n" + + " -PsiPackage: javax.servlet\n" + + " Class1.java\n", 4); + + doTest(false, false, "-Project\n" + + " -PsiPackage: com.package1\n" + + " Class1.java\n" + + " Class2.java\n" + + " Class4.java\n" + + " Form1.form\n" + + " Form1.java\n" + + " Form2.form\n" + + " PsiPackage: empty\n" + + " -PsiPackage: java\n" + + " Class1.java\n" + + " -PsiPackage: javax.servlet\n" + + " Class1.java\n", 3); + + } + + private void doTest(final boolean showModules, final boolean showLibraryContents, @NonNls final String expected, final int levels) { + final ProjectViewImpl projectView = (ProjectViewImpl)ProjectView.getInstance(myProject); + + projectView.setShowModules(showModules, PackageViewPane.ID); + + projectView.setShowLibraryContents(showLibraryContents, PackageViewPane.ID); + + projectView.setFlattenPackages(false, PackageViewPane.ID); + projectView.setHideEmptyPackages(true, PackageViewPane.ID); + + PackageViewPane packageViewPane = new PackageViewPane(myProject); + packageViewPane.createComponent(); + ((AbstractProjectTreeStructure) packageViewPane.getTreeStructure()).setProviders(new ResourceBundleGrouper(myProject)); + packageViewPane.updateFromRoot(true); + JTree tree = packageViewPane.getTree(); + TreeUtil.expand(tree, levels); + IdeaTestUtil.assertTreeEqual(tree, expected); + BaseProjectViewTestCase.checkContainsMethod(packageViewPane.getTreeStructure().getRootElement(), packageViewPane.getTreeStructure()); + Disposer.dispose(packageViewPane); + } + + @Override + protected String getTestPath() { + return "projectView"; + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java index d15dc3c2969c..901d404ed762 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java @@ -80,6 +80,10 @@ public class RenameMembersInplaceTest extends LightCodeInsightTestCase { doTestInplaceRename("bar"); } + public void testRenameFieldInIncompleteStatement() throws Exception { + doTestInplaceRename("bar"); + } + public void testNameSuggestion() throws Exception { configureByFile(BASE_PATH + "/" + getTestName(false) + ".java"); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java index a727714f85fa..8ecd54441f6a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java @@ -111,7 +111,7 @@ public class ReplaceConstructorWithBuilderTest extends MultiFileTestCase { final LinkedHashMap map = new LinkedHashMap(); final PsiMethod[] constructors = aClass.getConstructors(); for (PsiMethod constructor : constructors) { - ParameterData.createFromConstructor(constructor, map); + ParameterData.createFromConstructor(constructor, "set", map); } if (expectedDefaults != null) { for (Map.Entry entry : expectedDefaults.entrySet()) { diff --git a/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java b/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java index e0ffc7fc9b40..7af2b2c1a3af 100644 --- a/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java +++ b/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java @@ -15,6 +15,7 @@ */ package com.intellij.execution.filters; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.JavaPsiFacade; @@ -58,6 +59,10 @@ public class ExceptionInfoCache { return cached; } + if (DumbService.isDumb(myProject)) { + return Pair.create(PsiClass.EMPTY_ARRAY, PsiFile.EMPTY_ARRAY); + } + PsiClass[] classes = findClassesPreferringMyScope(className); if (classes.length == 0) { final int dollarIndex = className.indexOf('$'); diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java index a82c941c0fa2..a1d505a40259 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java @@ -33,6 +33,7 @@ class JavaPredefinedConfigurations { createSearchTemplateInfo(SSRBundle.message("predefined.configuration.string.literals"),"\"'_String\"",EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.all.expressions.of.some.type"),"'_Expression:[exprtype( SomeType )]",EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.sample.method.invokation.with.constant.argument"),"Integer.parseInt('_a:[script( \"com.intellij.psi.util.PsiUtil.isConstantExpression(__context__)\" )])",EXPRESSION_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.method.references"), "'_Qualifier::'methodName", EXPRESSION_TYPE), // Operators createSearchTemplateInfo(SSRBundle.message("predefined.configuration.block.dcls"),"{\n '_Type+ 'Var+ = '_Init*;\n '_BlockStatements*;\n}",OPERATOR_TYPE), @@ -90,7 +91,7 @@ class JavaPredefinedConfigurations { ), createSearchTemplateInfo( SSRBundle.message("predefined.configuration.implementors.of.interface.within.hierarchy"), - "class 'Class implements 'Interface:* {}", + "class 'Class implements '_Interface:* {}", CLASS_TYPE ), createSearchTemplateInfo( @@ -165,6 +166,7 @@ class JavaPredefinedConfigurations { createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.casts"),"( '_Type <'_GenericArgument+> ) '_Expr", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.type.var.substitutions.in.intanceof.with.generic.types"),"'_Expr instanceof '_Type <'Substitutions+> ", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.variables.of.generic.types"),"'_Type <'_GenericArgument+> 'Var = 'Init?;", GENERICS_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.diamond.operators"), "new 'ClassName<>('_Argument*)", GENERICS_TYPE), // Add comments and metadata createSearchTemplateInfo(SSRBundle.message("predefined.configuration.comments"),"/* 'CommentContent */", METADATA_TYPE), diff --git a/java/testFramework/src/com/intellij/testFramework/ResolveTestCase.java b/java/testFramework/src/com/intellij/testFramework/ResolveTestCase.java index e2cebe40700a..865a6f76ed30 100644 --- a/java/testFramework/src/com/intellij/testFramework/ResolveTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/ResolveTestCase.java @@ -1,6 +1,5 @@ - /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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,49 +16,75 @@ package com.intellij.testFramework; import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiManager; import com.intellij.psi.PsiReference; -import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; public abstract class ResolveTestCase extends PsiTestCase { - @NonNls protected static final String MARKER = ""; + protected static final String MARKER = ""; - protected PsiReference configureByFile(@NonNls String filePath) throws Exception{ + private Document myDocument; + + @Override + protected void tearDown() throws Exception { + if (myDocument != null) { + FileDocumentManager.getInstance().reloadFromDisk(myDocument); + } + + super.tearDown(); + } + + protected PsiReference configureByFile(@NotNull String filePath) throws Exception { return configureByFile(filePath, null); } - - protected PsiReference configureByFile(@TestDataFile @NonNls String filePath, @Nullable VirtualFile parentDir) throws Exception{ + + protected PsiReference configureByFile(@TestDataFile @NotNull String filePath, @Nullable VirtualFile parentDir) throws Exception { final String fullPath = getTestDataPath() + filePath; final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/')); assertNotNull("file " + filePath + " not found", vFile); - String fileText = StringUtil.convertLineSeparators(VfsUtil.loadText(vFile)); - - final String fileName = vFile.getName(); - - return configureByFileText(fileText, fileName, parentDir); + String fileText = StringUtil.convertLineSeparators(VfsUtilCore.loadText(vFile)); + return configureByFileText(fileText, vFile.getName(), parentDir); } protected PsiReference configureByFileText(String fileText, String fileName) throws Exception { return configureByFileText(fileText, fileName, null); } - - protected PsiReference configureByFileText(String fileText, String fileName, @Nullable final VirtualFile parentDir) throws Exception { + + protected PsiReference configureByFileText(String fileText, String fileName, @Nullable VirtualFile parentDir) throws Exception { int offset = fileText.indexOf(MARKER); assertTrue(offset >= 0); fileText = fileText.substring(0, offset) + fileText.substring(offset + MARKER.length()); - myFile = parentDir == null? createFile(myModule, fileName, fileText) : createFile(myModule, parentDir, fileName, fileText); + if (parentDir == null) { + myFile = createFile(myModule, fileName, fileText); + } + else { + VirtualFile existing = parentDir.findChild(fileName); + if (existing != null) { + myDocument = FileDocumentManager.getInstance().getDocument(existing); + assertNotNull(myDocument); + myDocument.setText(fileText); + myFile = PsiManager.getInstance(getProject()).findFile(existing); + assertNotNull(myFile); + assertEquals(fileText, myFile.getText()); + } + else { + myFile = createFile(myModule, parentDir, fileName, fileText); + } + } + PsiReference ref = myFile.findReferenceAt(offset); - assertNotNull(ref); - return ref; } diff --git a/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java b/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java index 55b55c55dfb7..0f4c5a1f53ef 100644 --- a/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java @@ -15,7 +15,6 @@ */ package com.intellij.testFramework; -import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; @@ -101,7 +100,6 @@ import java.io.File; } protected String getRootFiles() { - return " " + myModule.getModuleFile().getName() + "\n" + - " " + myProject.getName() + ProjectFileType.DOT_DEFAULT_EXTENSION + "\n"; + return " " + myModule.getModuleFile().getName() + "\n"; } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 4ce05d3d09bf..f55d73b8d6da 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -602,8 +602,10 @@ public class JavaBuilder extends ModuleLevelBuilder { if (baseDirectory != null) { //this is a temporary workaround to allow passing per-module compiler options for Eclipse compiler in form // -properties $MODULE_DIR$/.settings/org.eclipse.jdt.core.prefs + String stringToReplace = "$" + PathMacroUtil.MODULE_DIR_MACRO_NAME + "$"; + String moduleDirPath = FileUtil.toCanonicalPath(baseDirectory.getAbsolutePath()); for (String s : cached) { - options.add(StringUtil.replace(s, "$" + PathMacroUtil.MODULE_DIR_MACRO_NAME + "$", baseDirectory.getAbsolutePath())); + options.add(StringUtil.replace(s, stringToReplace, moduleDirPath)); } } else { diff --git a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java index 4455cf0d6767..bb197ca6b683 100644 --- a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java +++ b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java @@ -21,6 +21,8 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Comparing; +import com.intellij.ui.JBColor; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.ColorIcon; import com.intellij.util.ui.JBUI; @@ -118,11 +120,11 @@ public class HighlightDisplayLevel { @NotNull public static Icon createIconByMask(final Color renderColor) { - return new TheColorIcon(getEmptyIconDim(), renderColor); + return new MyColorIcon(getEmptyIconDim(), renderColor); } - public static class TheColorIcon extends ColorIcon implements ColoredIcon { - public TheColorIcon(int size, @NotNull Color color) { + private static class MyColorIcon extends ColorIcon implements ColoredIcon { + public MyColorIcon(int size, @NotNull Color color) { super(size, color); } @@ -130,12 +132,12 @@ public class HighlightDisplayLevel { public Color getColor() { return getIconColor(); } - } - + } + public interface ColoredIcon { Color getColor(); } - + public static class SingleColorIcon implements Icon, ColoredIcon { private final TextAttributesKey myKey; @@ -143,7 +145,13 @@ public class HighlightDisplayLevel { myKey = key; } + @NotNull public Color getColor() { + return ObjectUtils.notNull(getColorInner(), JBColor.GRAY); + } + + @Nullable + public Color getColorInner() { final EditorColorsManager manager = EditorColorsManager.getInstance(); if (manager != null) { TextAttributes attributes = manager.getGlobalScheme().getAttributes(myKey); diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index de4c9612f46e..a6a9770223a6 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -94,16 +94,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparatornull for default project */ + @Nullable @NonNls String getBasePath(); diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java index 306c478306be..1929cdd7f383 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java @@ -332,7 +332,7 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica return null; } - @Nullable + @NotNull public VirtualFile findOrCreateChildData(Object requestor, @NotNull @NonNls String name) throws IOException { final VirtualFile child = findChild(name); if (child != null) return child; diff --git a/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java b/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java index 4be3352d0ca7..d456542d5644 100644 --- a/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java +++ b/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; /** * @author peter - * @see com.intellij.psi.LanguageSubstitutors + * @see LanguageSubstitutors */ public abstract class LanguageSubstitutor { diff --git a/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java b/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java index 4b9f7a992a14..1408359d94ac 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java +++ b/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java @@ -25,6 +25,7 @@ import com.intellij.psi.StubBuilder; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.ILightStubFileElementType; +import com.intellij.psi.tree.IStubFileElementType; import com.intellij.util.containers.Stack; import gnu.trove.TIntStack; import org.jetbrains.annotations.NotNull; @@ -46,11 +47,18 @@ public class LightStubBuilder implements StubBuilder { } Language language = ((LanguageFileType)fileType).getLanguage(); final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType(); - if (!(contentType instanceof ILightStubFileElementType)) { - LOG.error("File is not of ILightStubFileElementType: " + contentType + ", " + file); + if (!(contentType instanceof IStubFileElementType)) { + LOG.error("File is not of IStubFileElementType: " + contentType + ", " + file); return null; } - tree = file.getNode().getLighterAST(); + + final FileASTNode node = file.getNode(); + if (contentType instanceof ILightStubFileElementType) { + tree = node.getLighterAST(); + } + else { + tree = new TreeBackedLighterAST(node); + } } else { FORCED_AST.set(null); } diff --git a/platform/core-impl/src/com/intellij/mock/MockProject.java b/platform/core-impl/src/com/intellij/mock/MockProject.java index 8e8016f1f659..72870cc78365 100644 --- a/platform/core-impl/src/com/intellij/mock/MockProject.java +++ b/platform/core-impl/src/com/intellij/mock/MockProject.java @@ -120,6 +120,7 @@ public class MockProject extends MockComponentManager implements Project { return myBaseDir; } + @Nullable @Override public String getBasePath() { return null; diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java index e0ed0dd9182e..8bdd768c91f1 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java @@ -150,7 +150,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu CheckUtil.checkWritable(this); VirtualFile parentFile = myFile.getParent(); if (parentFile == null) { - throw new IncorrectOperationException(VfsBundle.message("cannot.rename.root.directory")); + throw new IncorrectOperationException(VfsBundle.message("cannot.rename.root.directory", myFile.getPath())); } VirtualFile child = parentFile.findChild(name); if (child != null && !child.equals(myFile)) { diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java index b4dda74e39a6..a34c2c8b5539 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java @@ -126,10 +126,24 @@ public class FileManagerImpl implements FileManager { } } removeInvalidFilesAndDirs(false); + checkLanguageChange(); } }); } + private void checkLanguageChange() { + Map fileToPsiFileMap = new THashMap(myVFileToViewProviderMap); + myVFileToViewProviderMap.clear(); + for (Iterator iterator = fileToPsiFileMap.keySet().iterator(); iterator.hasNext();) { + VirtualFile vFile = iterator.next(); + Language language = getLanguage(vFile); + if (language != null && language != fileToPsiFileMap.get(vFile).getBaseLanguage()) { + iterator.remove(); + } + } + myVFileToViewProviderMap.putAll(fileToPsiFileMap); + } + public void forceReload(@NotNull VirtualFile vFile) { if (findCachedViewProvider(vFile) == null) { return; @@ -231,6 +245,11 @@ public class FileManagerImpl implements FileManager { @NotNull public FileViewProvider createFileViewProvider(@NotNull final VirtualFile file, boolean eventSystemEnabled) { Language language = getLanguage(file); + return createFileViewProvider(file, eventSystemEnabled, language); + } + + @NotNull + private FileViewProvider createFileViewProvider(@NotNull VirtualFile file, boolean eventSystemEnabled, Language language) { final FileViewProviderFactory factory = language == null ? FileTypeFileViewProviders.INSTANCE.forFileType(file.getFileType()) : LanguageFileViewProviders.INSTANCE.forLanguage(language); diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index f69f416bb07f..51b3dac1373f 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -18,10 +18,7 @@ package com.intellij.psi.impl.source; import com.intellij.extapi.psi.StubBasedPsiElementBase; import com.intellij.ide.util.PsiNavigationSupport; -import com.intellij.lang.ASTFactory; -import com.intellij.lang.ASTNode; -import com.intellij.lang.FileASTNode; -import com.intellij.lang.Language; +import com.intellij.lang.*; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -48,10 +45,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.SearchScope; import com.intellij.psi.stubs.*; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.ILazyParseableElementType; -import com.intellij.psi.tree.IStubFileElementType; -import com.intellij.psi.tree.TokenSet; +import com.intellij.psi.tree.*; import com.intellij.reference.SoftReference; import com.intellij.util.FileContentUtilCore; import com.intellij.util.IncorrectOperationException; @@ -256,7 +250,9 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF final Iterator> stubs = stubTree.getPlainList().iterator(); stubs.next(); // Skip file stub; final List> result = ContainerUtil.newArrayList(); - final StubBuilder builder = ((IStubFileElementType)getContentElementType()).getBuilder(); + final IStubFileElementType elementType = getElementTypeForStubBuilder(); + assert elementType != null; + final StubBuilder builder = elementType.getBuilder(); LazyParseableElement.setSuppressEagerPsiCreation(true); try { @@ -299,6 +295,12 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF return result; } + @Nullable + public IStubFileElementType getElementTypeForStubBuilder() { + final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(getLanguage()).getFileNodeType(); + return type instanceof IStubFileElementType ? (IStubFileElementType)type : null; + } + protected void reportStubAstMismatch(String message, StubTree stubTree, Document cachedDocument) { rebuildStub(); clearStub(STUB_PSI_MISMATCH); @@ -982,10 +984,10 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF if (tree == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); - IElementType contentElementType = getContentElementType(); - if (!(contentElementType instanceof IStubFileElementType)) { + IStubFileElementType contentElementType = getElementTypeForStubBuilder(); + if (contentElementType == null) { VirtualFile vFile = getVirtualFile(); - String message = "ContentElementType: " + contentElementType + "; file: " + this + + String message = "ContentElementType: " + getContentElementType() + "; file: " + this + "\n\t" + "Boolean.TRUE.equals(getUserData(BUILDING_STUB)) = " + Boolean.TRUE.equals(getUserData(BUILDING_STUB)) + "\n\t" + "getTreeElement() = " + getTreeElement() + "\n\t" + "vFile instanceof VirtualFileWithId = " + (vFile instanceof VirtualFileWithId) + @@ -994,7 +996,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF throw new AssertionError(message); } - StubElement currentStubTree = ((IStubFileElementType)contentElementType).getBuilder().buildStubTree(this); + StubElement currentStubTree = contentElementType.getBuilder().buildStubTree(this); if (currentStubTree == null) { throw new AssertionError("Stub tree wasn't built for " + contentElementType + "; file: " + this); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java index 9c93f1a868f7..582dfd0ca647 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java @@ -16,7 +16,6 @@ package com.intellij.psi.impl.source.codeStyle; import com.intellij.lang.*; -import com.intellij.openapi.command.AbnormalCommandTerminationException; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Key; import com.intellij.psi.*; @@ -125,7 +124,7 @@ public class CodeEditUtil { public static void checkForOuters(ASTNode element) { if (element instanceof OuterLanguageElement && element.getCopyableUserData(OUTER_OK) == null) { - throw new AbnormalCommandTerminationException(); + throw new IllegalArgumentException("Outer element " + element + " is not allowed here"); } ASTNode child = element.getFirstChildNode(); diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java index 99960ec65d66..94fc6b508990 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java @@ -449,7 +449,9 @@ public class TreeUtil { FileElement tree = file.getTreeElement(); assert tree != null : file; - final StubBuilder builder = ((IStubFileElementType)file.getContentElementType()).getBuilder(); + final IStubFileElementType type = file.getElementTypeForStubBuilder(); + assert type != null; + final StubBuilder builder = type.getBuilder(); tree.acceptTree(new RecursiveTreeElementWalkingVisitor() { @Override protected void visitNode(TreeElement node) { diff --git a/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java b/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java index 74e1f63e9900..f9d0135bbc35 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java @@ -25,7 +25,7 @@ import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IStubFileElementType; public class CumulativeStubVersion { - private static final int VERSION = 28; + private static final int VERSION = 29; public static int getCumulativeVersion() { int version = VERSION; diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java index f48bc38de414..8ab9df1d7334 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java @@ -17,6 +17,7 @@ package com.intellij.psi.stubs; import com.intellij.lang.Language; import com.intellij.lang.LanguageParserDefinitions; +import com.intellij.lang.TreeBackedLighterAST; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.util.Key; @@ -67,8 +68,6 @@ public class StubTreeBuilder { } else { final LanguageFileType languageFileType = (LanguageFileType)fileType; - Language l = languageFileType.getLanguage(); - final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); CharSequence contentAsText = inputData.getContentAsText(); FileContentImpl fileContent = (FileContentImpl)inputData; @@ -76,14 +75,15 @@ public class StubTreeBuilder { final FileViewProvider viewProvider = psi.getViewProvider(); psi = viewProvider.getStubBindingRoot(); psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, contentAsText); + final IStubFileElementType type = ((PsiFileImpl)psi).getElementTypeForStubBuilder(); // if we load AST, it should be easily gc-able. See PsiFileImpl.createTreeElementPointer() psi.getManager().startBatchFilesProcessingMode(); try { IStubFileElementType stubFileElementType; - if (type instanceof IStubFileElementType) { - stubFileElementType = (IStubFileElementType)type; + if (type != null) { + stubFileElementType = type; } else if (languageFileType instanceof SubstitutedFileType) { SubstitutedFileType substituted = (SubstitutedFileType)languageFileType; @@ -108,7 +108,11 @@ public class StubTreeBuilder { for (Pair stubbedRoot : stubbedRoots) { if (psi == stubbedRoot.second) continue; - final StubElement element = stubbedRoot.first.getBuilder().buildStubTree(stubbedRoot.second); + final StubBuilder stubbedRootBuilder = stubbedRoot.first.getBuilder(); + if (stubbedRootBuilder instanceof LightStubBuilder) { + LightStubBuilder.FORCED_AST.set(new TreeBackedLighterAST(psi.getNode())); + } + final StubElement element = stubbedRootBuilder.buildStubTree(stubbedRoot.second); if (element instanceof PsiFileStub) { stubs.add((PsiFileStub)element); } @@ -142,9 +146,9 @@ public class StubTreeBuilder { for (Language language : viewProvider.getLanguages()) { final PsiFile file = viewProvider.getPsi(language); if (file instanceof PsiFileImpl) { - final IElementType contentType = ((PsiFileImpl)file).getContentElementType(); - if (contentType instanceof IStubFileElementType) { - roots.add(Trinity.create(language, (IStubFileElementType)contentType, file)); + final IElementType type = ((PsiFileImpl)file).getElementTypeForStubBuilder(); + if (type != null) { + roots.add(Trinity.create(language, (IStubFileElementType)type, file)); } } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java index ae9812121828..fc95b7720b0e 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java @@ -296,7 +296,7 @@ public class DvcsUtil { } public static void addMappingIfSubRoot(@NotNull Project project, @NotNull String newRepositoryPath, @NotNull String vcsName) { - if (FileUtil.isAncestor(project.getBasePath(), newRepositoryPath, true)) { + if (project.getBasePath() != null && FileUtil.isAncestor(project.getBasePath(), newRepositoryPath, true)) { ProjectLevelVcsManager manager = ProjectLevelVcsManager.getInstance(project); manager.setDirectoryMappings(VcsUtil.addMapping(manager.getDirectoryMappings(), newRepositoryPath, vcsName)); } diff --git a/platform/icons/src/javaee/persistenceEmbeddable.png b/platform/icons/src/javaee/persistenceEmbeddable.png index 03f46d92bc53..ef5ac7d71413 100755 Binary files a/platform/icons/src/javaee/persistenceEmbeddable.png and b/platform/icons/src/javaee/persistenceEmbeddable.png differ diff --git a/platform/icons/src/javaee/persistenceEmbeddable@2x.png b/platform/icons/src/javaee/persistenceEmbeddable@2x.png index 0d4858bbc100..7cfc9fd795de 100755 Binary files a/platform/icons/src/javaee/persistenceEmbeddable@2x.png and b/platform/icons/src/javaee/persistenceEmbeddable@2x.png differ diff --git a/platform/icons/src/javaee/persistenceEntity.png b/platform/icons/src/javaee/persistenceEntity.png index 9f942f970782..8ed614d96bf0 100755 Binary files a/platform/icons/src/javaee/persistenceEntity.png and b/platform/icons/src/javaee/persistenceEntity.png differ diff --git a/platform/icons/src/javaee/persistenceEntity@2x.png b/platform/icons/src/javaee/persistenceEntity@2x.png index 8da8fa567716..b752905a75bf 100755 Binary files a/platform/icons/src/javaee/persistenceEntity@2x.png and b/platform/icons/src/javaee/persistenceEntity@2x.png differ diff --git a/platform/icons/src/javaee/persistenceMappedSuperclass.png b/platform/icons/src/javaee/persistenceMappedSuperclass.png index c65f565a1cf5..7e92fec44ae7 100755 Binary files a/platform/icons/src/javaee/persistenceMappedSuperclass.png and b/platform/icons/src/javaee/persistenceMappedSuperclass.png differ diff --git a/platform/icons/src/javaee/persistenceMappedSuperclass@2x.png b/platform/icons/src/javaee/persistenceMappedSuperclass@2x.png index 84231ab9ac4f..3ea7d6028983 100755 Binary files a/platform/icons/src/javaee/persistenceMappedSuperclass@2x.png and b/platform/icons/src/javaee/persistenceMappedSuperclass@2x.png differ diff --git a/platform/icons/src/welcome/project/remove-hover.png b/platform/icons/src/welcome/project/remove-hover.png new file mode 100755 index 000000000000..5ad066031a0b Binary files /dev/null and b/platform/icons/src/welcome/project/remove-hover.png differ diff --git a/platform/icons/src/welcome/project/remove-hover@2x.png b/platform/icons/src/welcome/project/remove-hover@2x.png new file mode 100755 index 000000000000..92e81d2c62c2 Binary files /dev/null and b/platform/icons/src/welcome/project/remove-hover@2x.png differ diff --git a/platform/icons/src/welcome/project/remove-hover@2x_dark.png b/platform/icons/src/welcome/project/remove-hover@2x_dark.png new file mode 100755 index 000000000000..45670e6f8640 Binary files /dev/null and b/platform/icons/src/welcome/project/remove-hover@2x_dark.png differ diff --git a/platform/icons/src/welcome/project/remove-hover_dark.png b/platform/icons/src/welcome/project/remove-hover_dark.png new file mode 100755 index 000000000000..5db2a4a66d93 Binary files /dev/null and b/platform/icons/src/welcome/project/remove-hover_dark.png differ diff --git a/platform/icons/src/welcome/project/remove.png b/platform/icons/src/welcome/project/remove.png new file mode 100755 index 000000000000..1e33bb2efd8c Binary files /dev/null and b/platform/icons/src/welcome/project/remove.png differ diff --git a/platform/icons/src/welcome/project/remove@2x.png b/platform/icons/src/welcome/project/remove@2x.png new file mode 100755 index 000000000000..95684493f363 Binary files /dev/null and b/platform/icons/src/welcome/project/remove@2x.png differ diff --git a/platform/icons/src/welcome/project/remove@2x_dark.png b/platform/icons/src/welcome/project/remove@2x_dark.png new file mode 100755 index 000000000000..3f9d3eba22e7 Binary files /dev/null and b/platform/icons/src/welcome/project/remove@2x_dark.png differ diff --git a/platform/icons/src/welcome/project/remove_dark.png b/platform/icons/src/welcome/project/remove_dark.png new file mode 100755 index 000000000000..4238c74433de Binary files /dev/null and b/platform/icons/src/welcome/project/remove_dark.png differ diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java index b45be7a17c22..ab40976da0f2 100644 --- a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java +++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java @@ -129,7 +129,7 @@ public abstract class StubProcessingHelperBase { String persistedStubTree = ((PsiFileStubImpl)stubTree.getRoot()).printTree(); String stubTreeJustBuilt = - ((PsiFileStubImpl)((IStubFileElementType)((PsiFileImpl)psiFile).getContentElementType()).getBuilder() + ((PsiFileStubImpl)((PsiFileImpl)psiFile).getElementTypeForStubBuilder().getBuilder() .buildStubTree(psiFile)).printTree(); StringBuilder builder = new StringBuilder(); diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java index a8a9d8efcbd7..a4ec415abcb6 100644 --- a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java +++ b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java @@ -65,7 +65,7 @@ public abstract class SettingsConnectionService { @Nullable private Map readSettings(final String... attributes) { return HttpRequests.request(mySettingsUrl) - .userAgent() + .productNameAsUserAgent() .connect(new HttpRequests.RequestProcessor>() { @Override public Map process(@NotNull HttpRequests.Request request) throws IOException { diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form index 89e8e9fcc7c9..fe82b9dea740 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form @@ -2,7 +2,7 @@
- + @@ -15,7 +15,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -170,16 +170,16 @@ - + - + - + @@ -189,7 +189,7 @@ - + @@ -197,7 +197,7 @@ - + @@ -205,83 +205,19 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -318,7 +254,7 @@ - + @@ -347,7 +283,7 @@ - + @@ -384,7 +320,7 @@ - + @@ -411,7 +347,7 @@ - + @@ -483,6 +419,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java index 19f7c804d3d6..84c44a22ab82 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java @@ -94,7 +94,7 @@ public class EditorOptionsPanel { private JCheckBox myCbUseSoftWrapsAtConsole; private JCheckBox myCbUseCustomSoftWrapIndent; private JTextField myCustomSoftWrapIndent; - private JCheckBox myCbShowAllSoftWraps; + private JCheckBox myCbShowSoftWrapsOnlyOnCaretLine; private JCheckBox myPreselectCheckBox; private JBCheckBox myCbShowQuickDocOnMouseMove; private JBLabel myQuickDocDelayLabel; @@ -177,7 +177,7 @@ public class EditorOptionsPanel { myCbUseSoftWrapsAtConsole.setSelected(editorSettings.isUseSoftWraps(SoftWrapAppliancePlaces.CONSOLE)); myCbUseCustomSoftWrapIndent.setSelected(editorSettings.isUseCustomSoftWrapIndent()); myCustomSoftWrapIndent.setText(Integer.toString(editorSettings.getCustomSoftWrapIndent())); - myCbShowAllSoftWraps.setSelected(editorSettings.isAllSoftWrapsShown()); + myCbShowSoftWrapsOnlyOnCaretLine.setSelected(!editorSettings.isAllSoftWrapsShown()); updateSoftWrapSettingsRepresentation(); myCbVirtualSpace.setSelected(editorSettings.isVirtualSpace()); @@ -282,7 +282,7 @@ public class EditorOptionsPanel { editorSettings.setUseSoftWraps(myCbUseSoftWrapsAtConsole.isSelected(), SoftWrapAppliancePlaces.CONSOLE); editorSettings.setUseCustomSoftWrapIndent(myCbUseCustomSoftWrapIndent.isSelected()); editorSettings.setCustomSoftWrapIndent(getCustomSoftWrapIndent()); - editorSettings.setAllSoftwrapsShown(myCbShowAllSoftWraps.isSelected()); + editorSettings.setAllSoftwrapsShown(!myCbShowSoftWrapsOnlyOnCaretLine.isSelected()); editorSettings.setVirtualSpace(myCbVirtualSpace.isSelected()); editorSettings.setCaretInsideTabs(myCbCaretInsideTabs.isSelected()); editorSettings.setAdditionalPageAtBottom(myCbVirtualPageAtBottom.isSelected()); @@ -443,7 +443,7 @@ public class EditorOptionsPanel { isModified |= isModified(myCbUseSoftWrapsAtConsole, editorSettings.isUseSoftWraps(SoftWrapAppliancePlaces.CONSOLE)); isModified |= isModified(myCbUseCustomSoftWrapIndent, editorSettings.isUseCustomSoftWrapIndent()); isModified |= editorSettings.getCustomSoftWrapIndent() != getCustomSoftWrapIndent(); - isModified |= isModified(myCbShowAllSoftWraps, editorSettings.isAllSoftWrapsShown()); + isModified |= isModified(myCbShowSoftWrapsOnlyOnCaretLine, !editorSettings.isAllSoftWrapsShown()); isModified |= isModified(myCbVirtualSpace, editorSettings.isVirtualSpace()); isModified |= isModified(myCbCaretInsideTabs, editorSettings.isCaretInsideTabs()); isModified |= isModified(myCbVirtualPageAtBottom, editorSettings.isAdditionalPageAtBottom()); @@ -555,8 +555,10 @@ public class EditorOptionsPanel { } private void updateSoftWrapSettingsRepresentation() { - myCbUseCustomSoftWrapIndent.setEnabled(myCbUseSoftWrapsAtEditor.isSelected() || myCbUseSoftWrapsAtConsole.isSelected()); + boolean softWrapsEnabled = myCbUseSoftWrapsAtEditor.isSelected() || myCbUseSoftWrapsAtConsole.isSelected(); + myCbUseCustomSoftWrapIndent.setEnabled(softWrapsEnabled); myCustomSoftWrapIndent.setEnabled(myCbUseCustomSoftWrapIndent.isEnabled() && myCbUseCustomSoftWrapIndent.isSelected()); + myCbShowSoftWrapsOnlyOnCaretLine.setEnabled(softWrapsEnabled); } public JComponent getComponent() { diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java index 72e30785d0c2..2585d91728c3 100644 --- a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java +++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java @@ -114,26 +114,8 @@ class PrintManager { painter = new MultiFilePainter(filesList); } - Pageable document = new Pageable() { - @Override - public int getNumberOfPages() { - return Pageable.UNKNOWN_NUMBER_OF_PAGES; - } - - @Override - public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException { - return pageFormat; - } - - @Override - public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException { - return painter; - } - }; - final PrinterJob printerJob = PrinterJob.getPrinterJob(); try { - printerJob.setPageable(document); printerJob.setPrintable(painter, pageFormat); if (!printerJob.printDialog()) { return; @@ -230,7 +212,8 @@ class PrintManager { if (doc == null) return null; EditorHighlighter highlighter = HighlighterFactory.createHighlighter(psiFile.getProject(), virtualFile); highlighter.setText(doc.getCharsSequence()); - return new TextPainter(doc, highlighter, virtualFile.getPresentableUrl(), psiFile, psiFile.getFileType(), editor); + return new TextPainter(doc, highlighter, virtualFile.getPresentableUrl(), virtualFile.getPresentableName(), + psiFile, psiFile.getFileType(), editor); } private static TextPainter initTextPainter(@NotNull final DocumentEx doc, final Project project) { @@ -249,6 +232,6 @@ class PrintManager { private static TextPainter doInitTextPainter(@NotNull final DocumentEx doc, Project project) { EditorHighlighter highlighter = HighlighterFactory.createHighlighter(project, "unknown"); highlighter.setText(doc.getCharsSequence()); - return new TextPainter(doc, highlighter, "unknown", project, FileTypes.PLAIN_TEXT, null); + return new TextPainter(doc, highlighter, "unknown", "unknown", project, FileTypes.PLAIN_TEXT, null); } } diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java index 22a420b725a8..7c84f5e637aa 100644 --- a/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java +++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java @@ -28,6 +28,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; @@ -45,6 +46,8 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.print.PageFormat; import java.awt.print.PrinterException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; class TextPainter extends BasePainter { @@ -62,32 +65,48 @@ class TextPainter extends BasePainter { private final Font myHeaderFont; private final EditorHighlighter myHighlighter; private final PrintSettings myPrintSettings; - private final String myFileName; + private final String myFullFileName; + private final String myShortFileName; private int myPageIndex; + private int myNumberOfPages = -1; private int mySegmentEnd; private final LineMarkerInfo[] myMethodSeparators; private int myCurrentMethodSeparator; private final CodeStyleSettings myCodeStyleSettings; private final FileType myFileType; + private boolean myPerformActualDrawing; + + private final String myPrintDate; + private final String myPrintTime; @NonNls private static final String DEFAULT_MEASURE_HEIGHT_TEXT = "A"; @NonNls private static final String DEFAULT_MEASURE_WIDTH_TEXT = "w"; + @NonNls private static final String HEADER_TOKEN_PAGE = "PAGE"; + @NonNls private static final String HEADER_TOKEN_TOTALPAGES = "TOTALPAGES"; @NonNls private static final String HEADER_TOKEN_FILE = "FILE"; + @NonNls private static final String HEADER_TOKEN_FILENAME = "FILENAME"; + @NonNls private static final String HEADER_TOKEN_DATE = "DATE"; + @NonNls private static final String HEADER_TOKEN_TIME = "TIME"; + + @NonNls private static final String DATE_FORMAT = "yyyy-MM-dd"; + @NonNls private static final String TIME_FORMAT = "HH:mm:ss"; public TextPainter(@NotNull DocumentEx editorDocument, EditorHighlighter highlighter, - String fileName, + String fullFileName, + String shortFileName, @NotNull PsiFile psiFile, FileType fileType, Editor editor) { - this(editorDocument, highlighter, fileName, psiFile.getProject(), fileType, + this(editorDocument, highlighter, fullFileName, shortFileName, psiFile.getProject(), fileType, FileSeparatorProvider.getInstance().getFileSeparators(psiFile, editorDocument, editor)); } public TextPainter(@NotNull DocumentEx editorDocument, EditorHighlighter highlighter, - String fileName, + String fullFileName, + String shortFileName, Project project, FileType fileType, List separators) { @@ -102,18 +121,26 @@ class TextPainter extends BasePainter { myBoldItalicFont = new Font(fontName, Font.BOLD | Font.ITALIC, fontSize); myHighlighter = highlighter; myHeaderFont = new Font(myPrintSettings.FOOTER_HEADER_FONT_NAME, Font.PLAIN, myPrintSettings.FOOTER_HEADER_FONT_SIZE); - myFileName = fileName; + myFullFileName = fullFileName; + myShortFileName = shortFileName; myRangeToPrint = editorDocument.createRangeMarker(0, myDocument.getTextLength()); myFileType = fileType; myMethodSeparators = separators != null ? separators.toArray(new LineMarkerInfo[separators.size()]) : new LineMarkerInfo[0]; myCurrentMethodSeparator = 0; + Date date = new Date(); + myPrintDate = new SimpleDateFormat(DATE_FORMAT).format(date); + myPrintTime = new SimpleDateFormat(TIME_FORMAT).format(date); } public void setSegment(int segmentStart, int segmentEnd) { + setSegment(myDocument.createRangeMarker(segmentStart, segmentEnd)); + } + + private void setSegment(RangeMarker marker) { if (myRangeToPrint != null) { myRangeToPrint.dispose(); } - myRangeToPrint = myDocument.createRangeMarker(segmentStart, segmentEnd); + myRangeToPrint = marker; } private float getLineHeight(Graphics g) { @@ -151,42 +178,104 @@ class TextPainter extends BasePainter { @Override public int print(final Graphics g, final PageFormat pageFormat, final int pageIndex) throws PrinterException { + if (myProgress.isCanceled()) { + return NO_SUCH_PAGE; + } + + final Graphics2D g2d = (Graphics2D)g; + + if (myNumberOfPages < 0) { + myProgress.setText(CodeEditorBundle.message("print.file.calculating.number.of.pages.progress")); + + myPerformActualDrawing = false; + + if (!calculateNumberOfPages(g2d, pageFormat)) { + return NO_SUCH_PAGE; + } + } + + myPerformActualDrawing = true; + return ApplicationManager.getApplication().runReadAction(new Computable() { @Override public Integer compute() { - if (myProgress.isCanceled() || myRangeToPrint == null || !myRangeToPrint.isValid()) { + if (!isValidRange(myRangeToPrint)) { return NO_SUCH_PAGE; } - int startOffset = myRangeToPrint.getStartOffset(); - myOffset = startOffset; - mySegmentEnd = myRangeToPrint.getEndOffset(); - myLineNumber = myDocument.getLineNumber(myOffset) + 1; - if (myOffset >= mySegmentEnd) { - return NO_SUCH_PAGE; - } isPrintingPass = !isPrintingPass; if (!isPrintingPass) { return PAGE_EXISTS; } - myProgress.setText(CodeEditorBundle.message("print.file.page.progress", myFileName, (pageIndex + 1))); + myProgress.setText(CodeEditorBundle.message("print.file.page.progress", myShortFileName, (pageIndex + 1), myNumberOfPages)); myPageIndex = pageIndex; - Graphics2D g2D = (Graphics2D) g; - Rectangle2D.Double clip = new Rectangle2D.Double(pageFormat.getImageableX(), pageFormat.getImageableY(), - pageFormat.getImageableWidth(), - pageFormat.getImageableHeight()); - draw(g2D, clip); + RangeMarker newRange = printPage(g2d, pageFormat, myRangeToPrint); + setSegment(newRange); - myRangeToPrint.dispose(); - // stop printing if there was no progress (to avoid an infinite loop) or if the whole range was processed - myRangeToPrint = myOffset > startOffset && myOffset < mySegmentEnd ? myDocument.createRangeMarker(myOffset, mySegmentEnd) : null; return PAGE_EXISTS; } }); } + private boolean calculateNumberOfPages(final Graphics2D g2d, final PageFormat pageFormat) { + myNumberOfPages = 0; + final Ref firstPage = new Ref(Boolean.TRUE); + final Ref tmpMarker = new Ref(); + while (ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + if (firstPage.get()) { + if (!isValidRange(myRangeToPrint)) { + return false; + } + tmpMarker.set(myDocument.createRangeMarker(myRangeToPrint.getStartOffset(), myRangeToPrint.getEndOffset())); + firstPage.set(Boolean.FALSE); + } + RangeMarker range = tmpMarker.get(); + if (!isValidRange(range)) { + return false; + } + tmpMarker.set(printPage(g2d, pageFormat, range)); + range.dispose(); + return true; + } + })) { + if (myProgress.isCanceled()) { + return false; + } + myNumberOfPages++; + } + if (!tmpMarker.isNull()) { + tmpMarker.get().dispose(); + } + return true; + } + + private static boolean isValidRange(RangeMarker range) { + return range != null && range.isValid() && range.getStartOffset() < range.getEndOffset(); + } + + /** + * Prints a pageful of text from a given range. Return a remaining range to print, or null if there's nothing left. + */ + private RangeMarker printPage(Graphics2D g2d, PageFormat pageFormat, RangeMarker range) { + assert isValidRange(range); + int startOffset = range.getStartOffset(); + int endOffset = range.getEndOffset(); + + myOffset = startOffset; + mySegmentEnd = endOffset; + myLineNumber = myDocument.getLineNumber(myOffset) + 1; + Rectangle2D.Double clip = new Rectangle2D.Double(pageFormat.getImageableX(), pageFormat.getImageableY(), + pageFormat.getImageableWidth(), pageFormat.getImageableHeight()); + + draw(g2d, clip); + + return myOffset > startOffset && myOffset < endOffset ? myDocument.createRangeMarker(myOffset, endOffset) : null; + } + private void draw(Graphics2D g2D, Rectangle2D.Double clip) { double headerHeight = drawHeader(g2D, clip); clip.y += headerHeight; @@ -209,7 +298,7 @@ class TextPainter extends BasePainter { } private void drawBorder(Graphics2D g, Rectangle2D clip) { - if (myPrintSettings.DRAW_BORDER) { + if (myPrintSettings.DRAW_BORDER && myPerformActualDrawing) { Color save = g.getColor(); g.setColor(Color.black); g.draw(clip); @@ -270,10 +359,8 @@ class TextPainter extends BasePainter { Point2D position = new Point2D.Double(0, clip.getY()); double lineY = position.getY(); - while (myCurrentMethodSeparator < myMethodSeparators.length) { - LineMarkerInfo marker = myMethodSeparators[myCurrentMethodSeparator]; - if (marker != null && marker.startOffset >= lIterator.getEnd()) break; - myCurrentMethodSeparator++; + if (myPerformActualDrawing) { + setInitialMethodSeparatorIndex(lIterator.getEnd()); } while (!hIterator.atEnd() && !lIterator.atEnd()) { @@ -290,14 +377,13 @@ class TextPainter extends BasePainter { lIterator.advance(); myLineNumber++; - if (myCurrentMethodSeparator < myMethodSeparators.length) { - LineMarkerInfo marker = myMethodSeparators[myCurrentMethodSeparator]; - if (marker != null && marker.startOffset < lEnd) { + if (myPerformActualDrawing) { + LineMarkerInfo marker = getMethodSeparator(lEnd); + if (marker != null) { Color save = g.getColor(); setForegroundColor(g, marker.separatorColor); UIUtil.drawLine(g, 0, (int)lineY, (int)clip.getWidth(), (int)lineY); setForegroundColor(g, save); - myCurrentMethodSeparator++; } } @@ -343,6 +429,25 @@ class TextPainter extends BasePainter { g.translate(-clip.getX(), 0); } + + private void setInitialMethodSeparatorIndex(int initialOffset) { + while (myCurrentMethodSeparator < myMethodSeparators.length) { + LineMarkerInfo marker = myMethodSeparators[myCurrentMethodSeparator]; + if (marker != null && marker.startOffset >= initialOffset) break; + myCurrentMethodSeparator++; + } + } + + private LineMarkerInfo getMethodSeparator(int currentOffset) { + if (myCurrentMethodSeparator < myMethodSeparators.length) { + LineMarkerInfo marker = myMethodSeparators[myCurrentMethodSeparator]; + if (marker != null && marker.startOffset < currentOffset) { + myCurrentMethodSeparator++; + return marker; + } + } + return null; + } private double drawHeader(Graphics2D g, Rectangle2D clip) { LineMetrics lineMetrics = getHeaderFooterLineMetrics(g); @@ -407,21 +512,23 @@ class TextPainter extends BasePainter { private double drawHeaderOrFooterLine(Graphics2D g, double x, double y, double w, String headerText, String alignment) { - headerText = convertHeaderText(headerText); - g.setFont(myHeaderFont); - g.setColor(Color.black); FontRenderContext fontRenderContext = g.getFontRenderContext(); LineMetrics lineMetrics = getHeaderFooterLineMetrics(g); float lineHeight = lineMetrics.getHeight(); - float descent = lineMetrics.getDescent(); - double width = myHeaderFont.getStringBounds(headerText, fontRenderContext).getWidth() + getCharWidth(g); - float yPos = (float) (lineHeight - descent + y); - if (PrintSettings.LEFT.equals(alignment)) { - drawStringToGraphics(g, headerText, x, yPos); - } else if (PrintSettings.CENTER.equals(alignment)) { - drawStringToGraphics(g, headerText, (float) (x + (w - width) / 2), yPos); - } else if (PrintSettings.RIGHT.equals(alignment)) { - drawStringToGraphics(g, headerText, (float) (x + w - width), yPos); + if (myPerformActualDrawing) { + headerText = convertHeaderText(headerText); + g.setFont(myHeaderFont); + g.setColor(Color.black); + float descent = lineMetrics.getDescent(); + double width = myHeaderFont.getStringBounds(headerText, fontRenderContext).getWidth() + getCharWidth(g); + float yPos = (float) (lineHeight - descent + y); + if (PrintSettings.LEFT.equals(alignment)) { + drawStringToGraphics(g, headerText, x, yPos); + } else if (PrintSettings.CENTER.equals(alignment)) { + drawStringToGraphics(g, headerText, (float) (x + (w - width) / 2), yPos); + } else if (PrintSettings.RIGHT.equals(alignment)) { + drawStringToGraphics(g, headerText, (float) (x + w - width), yPos); + } } return lineHeight; } @@ -437,8 +544,16 @@ class TextPainter extends BasePainter { if (isExpression) { if (HEADER_TOKEN_PAGE.equals(token)) { result.append(myPageIndex + 1); + } else if (HEADER_TOKEN_TOTALPAGES.equals(token)) { + result.append(myNumberOfPages); } else if (HEADER_TOKEN_FILE.equals(token)) { - result.append(myFileName); + result.append(myFullFileName); + } else if (HEADER_TOKEN_FILENAME.equals(token)) { + result.append(myShortFileName); + } else if (HEADER_TOKEN_DATE.equals(token)) { + result.append(myPrintDate); + } else if (HEADER_TOKEN_TIME.equals(token)) { + result.append(myPrintTime); } } else { result.append(token); @@ -475,7 +590,7 @@ class TextPainter extends BasePainter { } private void drawLineNumber(Graphics2D g, double x, double y) { - if (!myPrintSettings.PRINT_LINE_NUMBERS) { + if (!myPrintSettings.PRINT_LINE_NUMBERS || !myPerformActualDrawing) { return; } FontRenderContext fontRenderContext = (g).getFontRenderContext(); @@ -538,7 +653,7 @@ class TextPainter extends BasePainter { double xStart = position.getX(); double x = position.getX(); double y = getLineHeight(g) - getDescent(g) + position.getY(); - if (backColor != null) { + if (backColor != null && myPerformActualDrawing) { Color savedColor = g.getColor(); setBackgroundColor(g, backColor); double w = getTextSegmentWidth(text, myOffset, length, position.getX(), g); @@ -567,7 +682,7 @@ class TextPainter extends BasePainter { x += drawStringToGraphics(g, s, x, y); } - if (underscoredColor != null) { + if (underscoredColor != null && myPerformActualDrawing) { Color savedColor = g.getColor(); setForegroundColor(g, underscoredColor); double w = getTextSegmentWidth(text, myOffset, length, position.getX(), g); @@ -581,13 +696,17 @@ class TextPainter extends BasePainter { private double drawStringToGraphics(Graphics2D g, String s, double x, double y) { if (!myPrintSettings.PRINT_AS_GRAPHICS) { - g.drawString(s, (float) x, (float) y); + if (myPerformActualDrawing) { + g.drawString(s, (float)x, (float)y); + } return g.getFontMetrics().stringWidth(s); } else { GlyphVector v = g.getFont().createGlyphVector(g.getFontRenderContext(), s); - g.translate(x, y); - g.fill(v.getOutline()); - g.translate(-x, -y); + if (myPerformActualDrawing) { + g.translate(x, y); + g.fill(v.getOutline()); + g.translate(-x, -y); + } return v.getLogicalBounds().getWidth(); } @@ -635,9 +754,6 @@ class TextPainter extends BasePainter { @Override void dispose() { - if (myRangeToPrint != null) { - myRangeToPrint.dispose(); - myRangeToPrint = null; - } + setSegment(null); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 45effe8e781e..03691d0749e0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.actions; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.Result; import com.intellij.openapi.diagnostic.Logger; @@ -27,6 +28,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; @@ -52,8 +54,9 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class FormatChangedTextUtil { + public static final Key TEST_REVISION_CONTENT = Key.create("test.revision.content"); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil"); - + private FormatChangedTextUtil() { } @@ -251,6 +254,13 @@ public class FormatChangedTextUtil { return cachedChangedLines; } + if (ApplicationManager.getApplication().isUnitTestMode()) { + String testContent = file.getUserData(TEST_REVISION_CONTENT); + if (testContent != null) { + return calculateChangedTextRanges(file.getProject(), file, testContent); + } + } + Change change = ChangeListManager.getInstance(project).getChange(file.getVirtualFile()); if (change == null) { return ContainerUtilRt.emptyList(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index b34fcb858108..4dbdefc6c8ec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -45,6 +45,11 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); } + + public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel selectionModel) { + super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); + mySelectionModel = selectionModel; + } public RearrangeCodeProcessor(@NotNull Project project, @NotNull PsiFile file, diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index bcbd0fd6738d..d21ec363fd55 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -192,8 +192,13 @@ public class ReformatCodeAction extends AnAction implements DumbAware { processor = new ReformatCodeProcessor(project, file, range, !processSelectedText && processChangedTextOnly); } - if (rearrangeEntries && editor != null) { - processor = new RearrangeCodeProcessor(processor); + if (rearrangeEntries) { + if (processSelectedText && editor != null) { + processor = new RearrangeCodeProcessor(processor, editor.getSelectionModel()); + } + else { + processor = new RearrangeCodeProcessor(processor); + } } processor.run(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index aa7f2bf6485f..e485a812d2ce 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -91,7 +91,6 @@ public class DocumentationManager extends DockablePopupManager myDocInfoHintRef; private Component myPreviouslyFocused = null; @@ -291,26 +290,21 @@ public class DocumentationManager extends DockablePopupManager 0) { - if (objects[0] instanceof PsiElement) { - element = assertSameProject((PsiElement)objects[0]); - } - } + if (element == null && expressionList != null) { + element = expressionList; } if (element == null && file == null) return; //file == null for text field editor @@ -493,7 +487,6 @@ public class DocumentationManager extends DockablePopupManager() { - @Override - public String compute() { - return generateParameterInfoDocumentation(provider); - } - } - ); - if (doc != null) return doc; - } + if (provider instanceof ExternalDocumentationProvider) { final List urls = ApplicationManager.getApplication().runReadAction( new NullableComputable>() { @@ -1112,38 +1095,6 @@ public class DocumentationManager extends DockablePopupManager 0) { - @NonNls StringBuffer sb = null; - - for (Object o : objects) { - PsiElement parameter = null; - if (o instanceof PsiElement) { - parameter = (PsiElement)o; - } - - if (parameter != null) { - final SmartPsiElementPointer originalElement = parameter.getUserData(ORIGINAL_ELEMENT_KEY); - final String str2 = provider.generateDoc(parameter, originalElement != null ? originalElement.getElement() : null); - if (str2 == null) continue; - if (sb == null) sb = new StringBuffer(); - sb.append(str2); - sb.append("
"); - } - else { - sb = null; - break; - } - } - - if (sb != null) return sb.toString(); - } - return null; - } - @Override @Nullable public PsiElement getElement() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java index 3617c944e888..e8774cedeeb8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,11 @@ import com.intellij.navigation.GotoRelatedProvider; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; +import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.markup.HighlighterTargetArea; -import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.MarkupModel; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditor; @@ -214,24 +217,26 @@ public final class NavigationUtil { */ @SuppressWarnings("UseJBColor") public static TextAttributes patchAttributesColor(TextAttributes attributes, @NotNull TextRange range, @NotNull Editor editor) { - int lineStart = editor.offsetToLogicalPosition(range.getStartOffset()).line; - int lineEnd = editor.offsetToLogicalPosition(range.getEndOffset()).line; - for (RangeHighlighter highlighter : editor.getMarkupModel().getAllHighlighters()) { - if (!highlighter.isValid()) continue; - if (highlighter.getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE) { - int line = editor.offsetToLogicalPosition(highlighter.getStartOffset()).line; - if (line >= lineStart && line <= lineEnd) { - TextAttributes textAttributes = highlighter.getTextAttributes(); - if (textAttributes != null) { - Color color = textAttributes.getBackgroundColor(); - if (color != null && color.getBlue() > 128 && color.getRed() < 128 && color.getGreen() < 128) { - TextAttributes clone = attributes.clone(); - clone.setForegroundColor(Color.orange); - clone.setEffectColor(Color.orange); - return clone; - } - } - } + MarkupModel model = DocumentMarkupModel.forDocument(editor.getDocument(), editor.getProject(), false); + if (model != null) { + if (!((MarkupModelEx)model).processRangeHighlightersOverlappingWith(range.getStartOffset(), range.getEndOffset(), + new Processor() { + @Override + public boolean process(RangeHighlighterEx highlighter) { + if (highlighter.isValid() && highlighter.getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE) { + TextAttributes textAttributes = highlighter.getTextAttributes(); + if (textAttributes != null) { + Color color = textAttributes.getBackgroundColor(); + return !(color != null && color.getBlue() > 128 && color.getRed() < 128 && color.getGreen() < 128); + } + } + return true; + } + })) { + TextAttributes clone = attributes.clone(); + clone.setForegroundColor(Color.orange); + clone.setEffectColor(Color.orange); + return clone; } } return attributes; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java index ad77eb4967c1..2efdb422391b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java @@ -120,7 +120,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler { } } - if (searchInDescription) { + if (searchInDescription && !matchingTemplates.containsKey(template)) { String templateDescription = template.getDescription(); if (!prefixWithoutDots.isEmpty() && templateDescription != null && prefixSearchPattern.matcher(templateDescription).matches()) { matchingTemplates.put(template, prefixWithoutDots); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java index f5c48dc42ae6..e72ee5399f47 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java @@ -325,12 +325,24 @@ public class SeverityEditorDialog extends DialogWrapper { final ListModel listModel = myOptionsList.getModel(); final List order = new ArrayList(); for (int i = listModel.getSize() - 1; i >= 0; i--) { - final SeverityBasedTextAttributes info = - (SeverityBasedTextAttributes)listModel.getElementAt(i); + SeverityBasedTextAttributes info = (SeverityBasedTextAttributes)listModel.getElementAt(i); order.add(info.getSeverity()); if (!mySeverityRegistrar.isDefaultSeverity(info.getSeverity())) { infoTypes.remove(info); final Color stripeColor = info.getAttributes().getErrorStripeColor(); + final boolean exists = mySeverityRegistrar.getSeverity(info.getSeverity().getName()) != null; + if (exists) { + info.getType().getAttributesKey().getDefaultAttributes().setErrorStripeColor(stripeColor); + } else { + HighlightInfoType.HighlightInfoTypeImpl type = info.getType(); + TextAttributesKey key = type.getAttributesKey(); + final TextAttributes defaultAttributes = key.getDefaultAttributes().clone(); + defaultAttributes.setErrorStripeColor(stripeColor); + key = TextAttributesKey.createTextAttributesKey(key.getExternalName(), defaultAttributes); + type = new HighlightInfoType.HighlightInfoTypeImpl(type.getSeverity(null), key); + info = new SeverityBasedTextAttributes(info.getAttributes(), type); + } + mySeverityRegistrar.registerSeverity(info, stripeColor != null ? stripeColor : LightColors.YELLOW); } } diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java index ec55f74b3d42..8081b7f4a47e 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java @@ -246,7 +246,7 @@ public abstract class AbstractBlockWrapper { if (anchorBlock instanceof CompositeBlockWrapper) { List children = ((CompositeBlockWrapper)anchorBlock).getChildren(); for (AbstractBlockWrapper c : children) { - if (c.getStartOffset() != getStartOffset()) { + if (c.getStartOffset() != getStartOffset() && c.getStartOffset() < targetBlockStartOffset) { anchorBlock = c; break; } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java index 92085534bf98..b5aa184607e2 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java @@ -63,7 +63,7 @@ class FTManager { myOriginal = null; } - FTManager(FTManager original) { + FTManager(@NotNull FTManager original) { myOriginal = original; myName = original.getName(); myTemplatesDir = original.myTemplatesDir; @@ -77,15 +77,15 @@ class FTManager { } public void setScheme(FileTemplatesScheme scheme) { + mySortedTemplates = null; myScheme = scheme; - restoreDefaults(Collections.emptySet()); } @NotNull public Collection getAllTemplates(boolean includeDisabled) { List sorted = mySortedTemplates; if (sorted == null) { - sorted = new ArrayList(myTemplates.values()); + sorted = new ArrayList(getTemplates().values()); Collections.sort(sorted, new Comparator() { @Override public int compare(FileTemplateBase t1, FileTemplateBase t2) { @@ -115,7 +115,7 @@ class FTManager { */ @Nullable public FileTemplateBase getTemplate(@NotNull String templateQname) { - return myTemplates.get(templateQname); + return getTemplates().get(templateQname); } /** @@ -125,7 +125,7 @@ class FTManager { */ @Nullable public FileTemplateBase findTemplateByName(@NotNull String templateName) { - final FileTemplateBase template = myTemplates.get(templateName); + final FileTemplateBase template = getTemplates().get(templateName); if (template != null) { final boolean isEnabled = !(template instanceof BundledFileTemplate) || ((BundledFileTemplate)template).isEnabled(); if (isEnabled) { @@ -151,7 +151,7 @@ class FTManager { FileTemplateBase template = getTemplate(qName); if (template == null) { template = new CustomFileTemplate(name, extension); - myTemplates.put(qName, template); + getTemplates().put(qName, template); mySortedTemplates = null; } else { @@ -163,9 +163,9 @@ class FTManager { } public void removeTemplate(@NotNull String qName) { - final FileTemplateBase template = myTemplates.get(qName); + final FileTemplateBase template = getTemplates().get(qName); if (template instanceof CustomFileTemplate) { - myTemplates.remove(qName); + getTemplates().remove(qName); mySortedTemplates = null; } else if (template instanceof BundledFileTemplate){ @@ -190,7 +190,7 @@ class FTManager { } private void restoreDefaults(Set toDisable) { - myTemplates.clear(); + getTemplates().clear(); mySortedTemplates = null; for (DefaultTemplate template : myDefaultTemplates) { final BundledFileTemplate bundled = createAndStoreBundledTemplate(template); @@ -208,7 +208,7 @@ class FTManager { private BundledFileTemplate createAndStoreBundledTemplate(DefaultTemplate template) { final BundledFileTemplate bundled = new BundledFileTemplate(template, myInternal); final String qName = bundled.getQualifiedName(); - final FileTemplateBase previous = myTemplates.put(qName, bundled); + final FileTemplateBase previous = getTemplates().put(qName, bundled); mySortedTemplates = null; LOG.assertTrue(previous == null, "Duplicate bundled template " + qName + @@ -269,12 +269,6 @@ class FTManager { } public void saveTemplates() { - if (myOriginal != null) { - myOriginal.myDefaultTemplates.clear(); - myOriginal.myDefaultTemplates.addAll(myDefaultTemplates); - myOriginal.myTemplates.clear(); - myOriginal.myTemplates.putAll(myTemplates); - } final File configRoot = getConfigRoot(true); final File[] files = configRoot.listFiles(); @@ -399,4 +393,7 @@ class FTManager { return Pair.create(name, ext); } + public Map getTemplates() { + return myOriginal != null && myScheme == FileTemplatesScheme.DEFAULT ? myOriginal.myTemplates : myTemplates; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java index e4362587abbb..22699f8ebae2 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java @@ -149,7 +149,7 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc @Override public String getDisplayName() { - return IdeBundle.message("title.file.templates"); + return IdeBundle.message("title.edit.file.template"); } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java index 5776f4832645..fe126a1eb7a6 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java @@ -33,7 +33,6 @@ import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.SystemProperties; import com.intellij.util.text.DateFormatUtil; @@ -118,9 +117,7 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Pers @NotNull @Override public String getTemplatesDir() { - VirtualFile file = project.getProjectFile(); - assert file != null; - return new File(file.getParent().getCanonicalPath(), TEMPLATES_DIR).getPath(); + return new File(project.getBasePath(), Project.DIRECTORY_STORE_FOLDER + "/" + TEMPLATES_DIR).getPath(); } }; } @@ -145,7 +142,6 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Pers myScheme = scheme; for (FTManager manager : myAllManagers) { manager.setScheme(scheme); - manager.loadCustomizedContent(); } } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplatesLoader.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplatesLoader.java index 18188a7d3e04..a9423ad11f78 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplatesLoader.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplatesLoader.java @@ -107,11 +107,11 @@ public class FileTemplatesLoader { return new FTManager(myPatternsManager); } - public FTManager getCodeTemplatesManager() { + FTManager getCodeTemplatesManager() { return new FTManager(myCodeTemplatesManager); } - public FTManager getJ2eeTemplatesManager() { + FTManager getJ2eeTemplatesManager() { return new FTManager(myJ2eeTemplatesManager); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java index cfdde22d49f1..bd8ff2d059b9 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java @@ -133,21 +133,21 @@ public class ProjectViewDirectoryHelper { if (parentDir == null || skipDirectory(parentDir) && withSubDirectories) { addAllSubpackages(children, psiDirectory, moduleFileIndex, settings); } - PsiDirectory[] subdirs = psiDirectory.getSubdirectories(); - for (PsiDirectory subdir : subdirs) { - if (!skipDirectory(subdir)) { - continue; - } - VirtualFile directoryFile = subdir.getVirtualFile(); + if (withSubDirectories) { + PsiDirectory[] subdirs = psiDirectory.getSubdirectories(); + for (PsiDirectory subdir : subdirs) { + if (!skipDirectory(subdir)) { + continue; + } + VirtualFile directoryFile = subdir.getVirtualFile(); - if (Registry.is("ide.hide.excluded.files")) { - if (fileIndex.isExcluded(directoryFile)) continue; - } - else { - if (FileTypeRegistry.getInstance().isFileIgnored(directoryFile)) continue; - } + if (Registry.is("ide.hide.excluded.files")) { + if (fileIndex.isExcluded(directoryFile)) continue; + } + else { + if (FileTypeRegistry.getInstance().isFileIgnored(directoryFile)) continue; + } - if (withSubDirectories) { children.add(new PsiDirectoryNode(project, subdir, settings)); } } @@ -228,17 +228,23 @@ public class ProjectViewDirectoryHelper { for (PsiElement child : children) { LOG.assertTrue(child.isValid()); - final VirtualFile vFile; + if (!(child instanceof PsiFileSystemItem)) { + LOG.error("Either PsiFile or PsiDirectory expected as a child of " + child.getParent() + ", but was " + child); + continue; + } + final VirtualFile vFile = ((PsiFileSystemItem) child).getVirtualFile(); + if (vFile == null) { + continue; + } + if (moduleFileIndex != null && !moduleFileIndex.isInContent(vFile)) { + continue; + } if (child instanceof PsiFile) { - vFile = ((PsiFile)child).getVirtualFile(); - if (vFile != null) { - addNode(moduleFileIndex, vFile, container, PsiFileNode.class, child, viewSettings); - } + container.add(new PsiFileNode(child.getProject(), (PsiFile) child, viewSettings)); } else if (child instanceof PsiDirectory) { if (withSubDirectories) { PsiDirectory dir = (PsiDirectory)child; - vFile = dir.getVirtualFile(); if (!vFile.equals(projectFileIndex.getSourceRootForFile(vFile))) { // if is not a source root if (viewSettings.isHideEmptyMiddlePackages() && !skipDirectory(psiDir) && isEmptyMiddleDirectory(dir, true)) { processPsiDirectoryChildren(dir, directoryChildrenInProject(dir, viewSettings), @@ -246,31 +252,9 @@ public class ProjectViewDirectoryHelper { continue; } } - addNode(moduleFileIndex, vFile, container, PsiDirectoryNode.class, child, viewSettings); + container.add(new PsiDirectoryNode(child.getProject(), (PsiDirectory) child, viewSettings)); } } - else { - LOG.error("Either PsiFile or PsiDirectory expected as a child of " + child.getParent() + ", but was " + child); - } - } - } - - public void addNode(ModuleFileIndex moduleFileIndex, - VirtualFile vFile, - List container, - Class nodeClass, - PsiElement element, - final ViewSettings settings) { - // this check makes sense for classes not in library content only - if (moduleFileIndex != null && !moduleFileIndex.isInContent(vFile)) { - return; - } - - try { - container.add(ProjectViewNode.createTreeNode(nodeClass, element.getProject(), element, settings)); - } - catch (Exception e) { - LOG.error(e); } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewModuleGroupNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewModuleGroupNode.java index d13d5e9c1fe0..b0a67ca578ae 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewModuleGroupNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewModuleGroupNode.java @@ -48,11 +48,11 @@ public class ProjectViewModuleGroupNode extends ModuleGroupNode { if (roots.length == 1) { final PsiDirectory psi = PsiManager.getInstance(myProject).findDirectory(roots[0]); if (psi != null) { - return createTreeNode(PsiDirectoryNode.class, myProject, psi, getSettings()); + return new PsiDirectoryNode(myProject, psi, getSettings()); } } - return createTreeNode(ProjectViewModuleNode.class, getProject(), module, getSettings()); + return new ProjectViewModuleNode(getProject(), module, getSettings()); } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java index c020db91e017..9f7cc2f7ac57 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java @@ -133,16 +133,16 @@ public class ProjectViewProjectNode extends AbstractProjectNode { if (roots.length == 1) { final PsiDirectory psi = PsiManager.getInstance(myProject).findDirectory(roots[0]); if (psi != null) { - return createTreeNode(PsiDirectoryNode.class, myProject, psi, getSettings()); + return new PsiDirectoryNode(myProject, psi, getSettings()); } } - return createTreeNode(ProjectViewModuleNode.class, getProject(), module, getSettings()); + return new ProjectViewModuleNode(getProject(), module, getSettings()); } @Override protected AbstractTreeNode createModuleGroupNode(final ModuleGroup moduleGroup) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { - return createTreeNode(ProjectViewModuleGroupNode.class, getProject(), moduleGroup, getSettings()); + return new ProjectViewModuleGroupNode(getProject(), moduleGroup, getSettings()); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java index 26da55cbc21a..33e9be8eeadb 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java @@ -17,7 +17,6 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; -import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleTypeManager; @@ -47,8 +46,9 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM private final ModuleImpl myModule; @SuppressWarnings({"UnusedDeclaration"}) - public ModuleStoreImpl(@NotNull ComponentManagerImpl componentManager, @NotNull ModuleImpl module) { - super(componentManager); + public ModuleStoreImpl(@NotNull ModuleImpl module, @NotNull PathMacroManager pathMacroManager) { + super(pathMacroManager); + myModule = module; } @@ -252,6 +252,6 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM @NotNull @Override protected StateStorageManager createStateStorageManager() { - return new ModuleStateStorageManager(PathMacroManager.getInstance(getComponentManager()).createTrackingSubstitutor(), myModule); + return new ModuleStateStorageManager(myPathMacroManager.createTrackingSubstitutor(), myModule); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java index fd92723c6e95..2f15cd946c53 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.components.impl.stores; +import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; @@ -32,8 +33,8 @@ import java.util.List; import java.util.Set; public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { - public ProjectWithModulesStoreImpl(@NotNull ProjectImpl project) { - super(project); + public ProjectWithModulesStoreImpl(@NotNull ProjectImpl project, @NotNull PathMacroManager pathMacroManager) { + super(project, pathMacroManager); } @Override diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java index eaed20f2960d..31b38ef816f8 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java @@ -34,13 +34,10 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; -import com.intellij.ui.ColorUtil; import com.intellij.ui.docking.DockManager; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; -import java.awt.*; - /** * @author yole */ @@ -88,15 +85,6 @@ public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl { myProblemSolver.addProblemListener(myProblemListener); } - @Override - public Color getFileColor(@NotNull final VirtualFile file) { - Color color = super.getFileColor(file); - if (myProblemSolver.isProblemFile(file)) { - return ColorUtil.toAlpha(color, WaverGraphicsDecorator.WAVE_ALPHA_KEY); - } - return color; - } - @Override public boolean isProblem(@NotNull final VirtualFile file) { return myProblemSolver.isProblemFile(file); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java index d67c251e8fe0..e2738c3e021e 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java @@ -163,6 +163,7 @@ public class ProjectSdksModel implements SdkModel { LOG.assertTrue(projectJdk != null); if (ArrayUtilRt.find(allJdks, projectJdk) == -1) { jdkTable.addJdk(projectJdk); + jdkTable.updateJdk(projectJdk, myProjectSdks.get(projectJdk)); } } } diff --git a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java index e0fcb7440100..0433c92ebf5b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java +++ b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java @@ -142,13 +142,15 @@ public class RegistryUi implements Disposable { public void keyPressed(@NotNull KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_SPACE) { int row = myTable.getSelectedRow(); - RegistryValue rv = myModel.getRegistryValue(row); - if (rv.isBoolean()) { - rv.setValue(!rv.asBoolean()); - keyChanged(rv.getKey()); - for (int i : new int[]{0, 1, 2}) myModel.fireTableCellUpdated(row, i); - revaliateActions(); - if (search.isPopupActive()) search.hidePopup(); + if (row != -1) { + RegistryValue rv = myModel.getRegistryValue(row); + if (rv.isBoolean()) { + rv.setValue(!rv.asBoolean()); + keyChanged(rv.getKey()); + for (int i : new int[]{0, 1, 2}) myModel.fireTableCellUpdated(row, i); + revaliateActions(); + if (search.isPopupActive()) search.hidePopup(); + } } } } diff --git a/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java b/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java index 792fdc40d45e..ac0af0927218 100644 --- a/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java +++ b/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java @@ -173,7 +173,7 @@ public class DownloadUtil { try { HttpRequests.request(location) - .userAgent() + .productNameAsUserAgent() .connect(new HttpRequests.RequestProcessor() { @Override public Object process(@NotNull HttpRequests.Request request) throws IOException { @@ -183,7 +183,7 @@ public class DownloadUtil { NetUtils.copyStreamContent(progress, request.getInputStream(), output, contentLength); } catch (IOException e) { - throw new IOException(HttpRequests.createErrorMessage(e, request), e); + throw new IOException(HttpRequests.createErrorMessage(e, request, true), e); } return null; } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java index fd26822af52d..5f75e2f813c2 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java @@ -36,7 +36,9 @@ public class ManageButton extends ComboBoxAction implements DumbAware { public ManageButton(final ManageButtonBuilder builder) { myBuilder = builder; getTemplatePresentation().setText("Manage"); - setSmallVariant(false); + if (SystemInfo.isMac) { + setSmallVariant(false); + } } public JComponent build() { diff --git a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java index cd9d1fcf49e2..5598abe47742 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java @@ -333,6 +333,11 @@ public class GeneralCommandLine implements UserDataHolder { environment.putAll(myEnvParams); } } + if (SystemInfo.isWindows) { + // (Windows) An environment variable with empty name is incorrect. + // It'll end up in "CreateProcess error=87, The parameter is incorrect". + environment.remove(""); + } } /** diff --git a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java index 712e9e8bbc5b..505e78e2a09f 100644 --- a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java +++ b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java @@ -69,14 +69,59 @@ public class ScreenUtil { } public static Shape getAllScreensShape() { - Rectangle[] rectangles = getAllScreenBounds(); + GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (devices.length == 0) { + return new Rectangle(); + } + if (devices.length == 1) { + return getScreenRectangle(devices[0]); + } Area area = new Area(); - for (Rectangle rectangle : rectangles) { - area.add(new Area(rectangle)); + for (GraphicsDevice device : devices) { + area.add(new Area(getScreenRectangle(device))); } return area; } + /** + * Returns the smallest rectangle that encloses a visible area of every screen. + * + * @return the smallest rectangle that encloses a visible area of every screen + */ + public static Rectangle getAllScreensRectangle() { + GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (devices.length == 0) { + return new Rectangle(); + } + if (devices.length == 1) { + return getScreenRectangle(devices[0]); + } + int minX = 0; + int maxX = 0; + int minY = 0; + int maxY = 0; + for (GraphicsDevice device : devices) { + Rectangle rectangle = getScreenRectangle(device); + int x = rectangle.x; + if (minX > x) { + minX = x; + } + x += rectangle.width; + if (maxX < x) { + maxX = x; + } + int y = rectangle.y; + if (minY > y) { + minY = y; + } + y += rectangle.height; + if (maxY < y) { + maxY = y; + } + } + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + public static Rectangle getScreenRectangle(@NotNull Point p) { return getScreenRectangle(p.x, p.y); } diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index 70bd84afec60..2e24a9f70e01 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -19,8 +19,10 @@ import com.intellij.ide.BrowserUtil; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -37,6 +39,8 @@ import javax.swing.*; import javax.swing.border.Border; import javax.swing.tree.TreeCellRenderer; import java.awt.*; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -672,6 +676,9 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co g.drawString(fragment, offset, textBaseline); } + // for some reason strokeState here may be incorrect, resetting the stroke helps + g.setStroke(g.getStroke()); + // 1. Strikeout effect if (attributes.isStrikeout()) { final int strikeOutAt = textBaseline + (metrics.getDescent() - metrics.getAscent()) / 2; @@ -679,13 +686,24 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co } // 2. Waved effect if (attributes.isWaved()) { - if (attributes.getWaveColor() != null) { - g.setColor(attributes.getWaveColor()); - } - final int wavedAt = textBaseline + 1; - for (int x = offset; x <= offset + fragmentWidth; x += 4) { - UIUtil.drawLine(g, x, wavedAt, x + 2, wavedAt + 2); - UIUtil.drawLine(g, x + 3, wavedAt + 1, x + 4, wavedAt); + GraphicsConfig config = GraphicsUtil.setupAAPainting(g); + Stroke oldStroke = g.getStroke(); + try { + g.setStroke(new BasicStroke(.7F)); + if (attributes.getWaveColor() != null) { + g.setColor(attributes.getWaveColor()); + } + final int wavedAt = textBaseline + 1; + GeneralPath wavePath = new GeneralPath(PathIterator.WIND_EVEN_ODD); + wavePath.moveTo(offset, wavedAt); + for (int x = offset; x <= offset + fragmentWidth; x += 4) { + wavePath.lineTo(x + 2, wavedAt + 2); + wavePath.lineTo(x + 4, wavedAt); + } + g.draw(wavePath); + } finally { + config.restore(); + g.setStroke(oldStroke); } } // 3. Underline diff --git a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java index 52c15afe94c4..66c974b5bbcf 100644 --- a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java @@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; import javax.swing.plaf.basic.BasicLabelUI; +import javax.swing.plaf.synth.SynthGraphicsUtils; +import javax.swing.plaf.synth.SynthStyle; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; @@ -43,10 +45,10 @@ import java.util.Set; public class LinkLabel extends JLabel { protected boolean myUnderline; - private LinkListener myLinkListener; + private LinkListener myLinkListener; private T myLinkData; - private static final Set ourVisitedLinks = new HashSet(); + private static final Set ourVisitedLinks = new HashSet(); private boolean myIsLinkActive; @@ -68,11 +70,11 @@ public class LinkLabel extends JLabel { this(text, icon, null, null, null); } - public LinkLabel(String text, @Nullable Icon icon, @Nullable LinkListener aListener) { + public LinkLabel(String text, @Nullable Icon icon, @Nullable LinkListener aListener) { this(text, icon, aListener, null, null); } - public LinkLabel(String text, @Nullable Icon icon, @Nullable LinkListener aListener, @Nullable T aLinkData) { + public LinkLabel(String text, @Nullable Icon icon, @Nullable LinkListener aListener, @Nullable T aLinkData) { this(text, icon, aListener, aLinkData, null); } @@ -100,7 +102,7 @@ public class LinkLabel extends JLabel { myHoveringIcon = iconForHovering; } - public void setListener(LinkListener listener, @Nullable T linkData) { + public void setListener(LinkListener listener, @Nullable T linkData) { myLinkListener = listener; myLinkData = linkData; } @@ -145,7 +147,7 @@ public class LinkLabel extends JLabel { boolean underline = myUnderline && myPaintUnderline; if (underline) { - Rectangle bounds = getTextBounds(); + Rectangle bounds = getBounds(false); // get calculated text bounds if (bounds != null) { int lineY = bounds.y + bounds.height - 1; g.drawLine(bounds.x, lineY, bounds.x + bounds.width, lineY); @@ -226,7 +228,7 @@ public class LinkLabel extends JLabel { } } if (getText() != null) { - Rectangle bounds = getTextBounds(); + Rectangle bounds = getBounds(false); // get calculated text bounds if (bounds != null) { return bounds.contains(pt.x + insets.left, pt.y + insets.top); } @@ -346,15 +348,32 @@ public class LinkLabel extends JLabel { myPaintDefaultIcon = paintDefaultIcon; } - private Rectangle getTextBounds() { + private Rectangle getBounds(boolean icon) { try { - Field field = BasicLabelUI.class.getDeclaredField("paintTextR"); - field.setAccessible(true); - Rectangle labelBounds = (Rectangle)field.get(getUI()); - return labelBounds.isEmpty() ? null : labelBounds; + Object ui = getUI(); + Class type = ui.getClass(); + String name = type.getSimpleName(); + if (name.equals("AlloyIdeaLabelUI")) { + return getValue(ui, type.getSuperclass(), icon ? "b" : "c"); + } + if (name.equals("AlloyLabelUI")) { + return getValue(ui, type, icon ? "b" : "c"); + } + if (name.equals("SynthLabelUI")) { + SynthStyle style = getValue(ui, type, "style"); + return getValue(style.getGraphicsUtils(null), SynthGraphicsUtils.class, icon ? "paintIconR" : "paintTextR"); + } + return getValue(ui, BasicLabelUI.class, icon ? "paintIconR" : "paintTextR"); } catch (Exception ignored) { return null; } } + + @SuppressWarnings("unchecked") + private static T getValue(Object object, Class type, String name) throws Exception { + Field field = type.getDeclaredField(name); + field.setAccessible(true); + return (T)field.get(object); + } } diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index 919317277b8a..9b6201ecf345 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -741,7 +741,8 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component TableColumn column = getColumnModel().getColumn(columnToPack); int currentWidth = column.getWidth(); int expandedWidth = getExpandedColumnWidth(columnToPack); - int newWidth = currentWidth >= expandedWidth ? getPreferredHeaderWidth(columnToPack) : expandedWidth; + int newWidth = getColumnModel().getColumnMargin() + + (currentWidth >= expandedWidth ? getPreferredHeaderWidth(columnToPack) : expandedWidth); setResizingColumn(column); column.setWidth(newWidth); diff --git a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java index 710a06751587..7012dd83d476 100644 --- a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java +++ b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java @@ -17,25 +17,19 @@ package com.intellij.util.io; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.ArrayUtil; -import com.intellij.util.ReflectionUtil; -import com.intellij.util.SystemProperties; import com.intellij.util.net.HTTPMethod; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.NetUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.HttpURLConnection; @@ -55,9 +49,9 @@ import java.util.zip.GZIPInputStream; * }); * } */ -public abstract class HttpRequests { - private static final boolean ourWrapClassLoader = - SystemInfo.isJavaVersionAtLeast("1.7") && !SystemProperties.getBooleanProperty("idea.parallel.class.loader", true); +public final class HttpRequests { + private HttpRequests() { + } public interface Request { @NotNull @@ -84,155 +78,9 @@ public abstract class HttpRequests { T process(@NotNull Request request) throws IOException; } - protected HttpRequests() { - } - - @NotNull - public static String createErrorMessage(@NotNull IOException e, @NotNull Request request) throws IOException { - URLConnection connection = request.getConnection(); - String errorMessage = "Cannot download '" + connection.getURL().toExternalForm() + "': " + e.getMessage() + "\n, headers: " + connection.getHeaderFields(); - if (connection instanceof HttpURLConnection) { - HttpURLConnection httpConnection = (HttpURLConnection)connection; - errorMessage += "\n, response: " + httpConnection.getResponseCode() + ' ' + httpConnection.getResponseMessage(); - } - return errorMessage; - } - - public abstract static class RequestBuilder { - private final String myUrl; - private int myConnectTimeout = HttpConfigurable.CONNECTION_TIMEOUT; - private int myTimeout = HttpConfigurable.READ_TIMEOUT; - private int myRedirectLimit = HttpConfigurable.REDIRECT_LIMIT; - private boolean myGzip = true; - private boolean myForceHttps; - private HostnameVerifier myHostnameVerifier; - private String myUserAgent; - private String myAccept; - - private HTTPMethod myMethod; - - protected RequestBuilder(@NotNull String url) { - myUrl = url; - } - - @NotNull - public RequestBuilder connectTimeout(int value) { - myConnectTimeout = value; - return this; - } - - @NotNull - public RequestBuilder readTimeout(int value) { - myTimeout = value; - return this; - } - - @NotNull - public RequestBuilder redirectLimit(int redirectLimit) { - myRedirectLimit = redirectLimit; - return this; - } - - @NotNull - public RequestBuilder gzip(boolean value) { - myGzip = value; - return this; - } - - @NotNull - public RequestBuilder forceHttps(boolean forceHttps) { - myForceHttps = forceHttps; - return this; - } - - @NotNull - public RequestBuilder hostNameVerifier(@Nullable HostnameVerifier hostnameVerifier) { - myHostnameVerifier = hostnameVerifier; - return this; - } - - @NotNull - public RequestBuilder userAgent(@Nullable String userAgent) { - myUserAgent = userAgent; - return this; - } - - @NotNull - public abstract RequestBuilder userAgent(); - - @NotNull - public RequestBuilder accept(@Nullable String mimeType) { - myAccept = mimeType; - return this; - } - - public T connect(@NotNull RequestProcessor processor) throws IOException { - // todo[r.sh] drop condition in IDEA 15 - if (ourWrapClassLoader) { - return wrapAndProcess(this, processor); - } - else { - return process(this, processor); - } - } - - public T connect(@NotNull RequestProcessor processor, T errorValue, @Nullable Logger logger) { - try { - return connect(processor); - } - catch (Throwable e) { - if (logger != null) { - logger.warn(e); - } - return errorValue; - } - } - - public void saveToFile(@NotNull final File file, @Nullable final ProgressIndicator indicator) throws IOException { - connect(new HttpRequests.RequestProcessor() { - @Override - public Void process(@NotNull HttpRequests.Request request) throws IOException { - request.saveToFile(file, indicator); - return null; - } - }); - } - - @NotNull - public byte[] readBytes(@Nullable final ProgressIndicator indicator) throws IOException { - return connect(new HttpRequests.RequestProcessor() { - @Override - public byte[] process(@NotNull HttpRequests.Request request) throws IOException { - return request.readBytes(indicator); - } - }); - } - - @NotNull - public String readString(@Nullable final ProgressIndicator indicator) throws IOException { - return connect(new HttpRequests.RequestProcessor() { - @Override - public String process(@NotNull HttpRequests.Request request) throws IOException { - int contentLength = request.getConnection().getContentLength(); - BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(contentLength > 0 ? contentLength : 16 * 1024); - NetUtils.copyStreamContent(indicator, request.getInputStream(), out, contentLength); - return new String(out.getInternalBuffer(), 0, out.size(), getCharset(request)); - } - }); - } - } - @NotNull public static RequestBuilder request(@NotNull String url) { - if (ApplicationManager.getApplication() == null) { - try { - return ((HttpRequests)ReflectionUtil.newInstance(Class.forName("com.intellij.util.io.HttpRequestsImpl"))).createRequestBuilder(url); - } - catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - return ServiceManager.getService(HttpRequests.class).createRequestBuilder(url); + return new RequestBuilder(url); } @NotNull @@ -242,9 +90,22 @@ public abstract class HttpRequests { return builder; } - protected abstract RequestBuilder createRequestBuilder(@NotNull String url); + @NotNull + public static String createErrorMessage(@NotNull IOException e, @NotNull Request request, boolean includeHeaders) throws IOException { + URLConnection connection = request.getConnection(); + StringBuilder builder = new StringBuilder(); + builder.append("Cannot download '").append(connection.getURL().toExternalForm()).append("': ").append(e.getMessage()); + if (includeHeaders) { + builder.append("\n, headers: ").append(connection.getHeaderFields()); + } + if (connection instanceof HttpURLConnection) { + HttpURLConnection httpConnection = (HttpURLConnection)connection; + builder.append("\n, response: ").append(httpConnection.getResponseCode()).append(' ').append(httpConnection.getResponseMessage()); + } + return builder.toString(); + } - private static T wrapAndProcess(RequestBuilder builder, RequestProcessor processor) throws IOException { + static T wrapAndProcess(RequestBuilder builder, RequestProcessor processor) throws IOException { // hack-around for class loader lock in sun.net.www.protocol.http.NegotiateAuthentication (IDEA-131621) ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0], oldClassLoader)); @@ -257,7 +118,7 @@ public abstract class HttpRequests { } @NotNull - private static Charset getCharset(@NotNull Request request) throws IOException { + static Charset getCharset(@NotNull Request request) throws IOException { String contentEncoding = request.getConnection().getContentEncoding(); if (contentEncoding != null) { try { @@ -269,7 +130,7 @@ public abstract class HttpRequests { return CharsetToolkit.UTF8_CHARSET; } - private static T process(final RequestBuilder builder, RequestProcessor processor) throws IOException { + static T process(final RequestBuilder builder, RequestProcessor processor) throws IOException { class RequestImpl implements Request { private URLConnection myConnection; private InputStream myInputStream; @@ -354,7 +215,7 @@ public abstract class HttpRequests { deleteFile = false; } catch (IOException e) { - throw new IOException(createErrorMessage(e, this), e); + throw new IOException(createErrorMessage(e, this, false), e); } finally { out.close(); diff --git a/platform/platform-api/src/com/intellij/util/io/ProgressMonitorInputStream.java b/platform/platform-api/src/com/intellij/util/io/ProgressMonitorInputStream.java index 59231206cbbb..369e4fd49c82 100644 --- a/platform/platform-api/src/com/intellij/util/io/ProgressMonitorInputStream.java +++ b/platform/platform-api/src/com/intellij/util/io/ProgressMonitorInputStream.java @@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; final class ProgressMonitorInputStream extends InputStream { private final ProgressIndicator indicator; @@ -41,12 +40,8 @@ final class ProgressMonitorInputStream extends InputStream { return c; } - private void updateProgress(long increment) throws InterruptedIOException { - if (indicator.isCanceled()) { - InterruptedIOException exception = new InterruptedIOException("progress"); - exception.bytesTransferred = (int)count; - throw exception; - } + private void updateProgress(long increment) { + indicator.checkCanceled(); if (increment > 0) { count += increment; indicator.setFraction((double)count / available); diff --git a/platform/platform-api/src/com/intellij/util/io/RequestBuilder.java b/platform/platform-api/src/com/intellij/util/io/RequestBuilder.java new file mode 100644 index 000000000000..a07a91d3b6e8 --- /dev/null +++ b/platform/platform-api/src/com/intellij/util/io/RequestBuilder.java @@ -0,0 +1,169 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.io; + +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationInfo; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; +import com.intellij.util.SystemProperties; +import com.intellij.util.net.HTTPMethod; +import com.intellij.util.net.HttpConfigurable; +import com.intellij.util.net.NetUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.net.ssl.HostnameVerifier; +import java.io.File; +import java.io.IOException; + +public final class RequestBuilder { + private static final boolean ourWrapClassLoader = + SystemInfo.isJavaVersionAtLeast("1.7") && !SystemProperties.getBooleanProperty("idea.parallel.class.loader", true); + + final String myUrl; + int myConnectTimeout = HttpConfigurable.CONNECTION_TIMEOUT; + int myTimeout = HttpConfigurable.READ_TIMEOUT; + int myRedirectLimit = HttpConfigurable.REDIRECT_LIMIT; + boolean myGzip = true; + boolean myForceHttps; + HostnameVerifier myHostnameVerifier; + String myUserAgent; + String myAccept; + + HTTPMethod myMethod; + + RequestBuilder(@NotNull String url) { + myUrl = url; + } + + @NotNull + public RequestBuilder connectTimeout(int value) { + myConnectTimeout = value; + return this; + } + + @NotNull + public RequestBuilder readTimeout(int value) { + myTimeout = value; + return this; + } + + @NotNull + public RequestBuilder redirectLimit(int redirectLimit) { + myRedirectLimit = redirectLimit; + return this; + } + + @NotNull + public RequestBuilder gzip(boolean value) { + myGzip = value; + return this; + } + + @NotNull + public RequestBuilder forceHttps(boolean forceHttps) { + myForceHttps = forceHttps; + return this; + } + + @NotNull + public RequestBuilder hostNameVerifier(@Nullable HostnameVerifier hostnameVerifier) { + myHostnameVerifier = hostnameVerifier; + return this; + } + + @NotNull + public RequestBuilder userAgent(@Nullable String userAgent) { + myUserAgent = userAgent; + return this; + } + + @NotNull + public RequestBuilder productNameAsUserAgent() { + Application app = ApplicationManager.getApplication(); + if (app != null && !app.isDisposed()) { + return userAgent(ApplicationInfo.getInstance().getVersionName()); + } + else { + return userAgent("IntelliJ"); + } + } + + @NotNull + public RequestBuilder accept(@Nullable String mimeType) { + myAccept = mimeType; + return this; + } + + public T connect(@NotNull HttpRequests.RequestProcessor processor) throws IOException { + // todo[r.sh] drop condition in IDEA 15 + if (ourWrapClassLoader) { + return HttpRequests.wrapAndProcess(this, processor); + } + else { + return HttpRequests.process(this, processor); + } + } + + public T connect(@NotNull HttpRequests.RequestProcessor processor, T errorValue, @Nullable Logger logger) { + try { + return connect(processor); + } + catch (Throwable e) { + if (logger != null) { + logger.warn(e); + } + return errorValue; + } + } + + public void saveToFile(@NotNull final File file, @Nullable final ProgressIndicator indicator) throws IOException { + connect(new HttpRequests.RequestProcessor() { + @Override + public Void process(@NotNull HttpRequests.Request request) throws IOException { + request.saveToFile(file, indicator); + return null; + } + }); + } + + @NotNull + public byte[] readBytes(@Nullable final ProgressIndicator indicator) throws IOException { + return connect(new HttpRequests.RequestProcessor() { + @Override + public byte[] process(@NotNull HttpRequests.Request request) throws IOException { + return request.readBytes(indicator); + } + }); + } + + @NotNull + public String readString(@Nullable final ProgressIndicator indicator) throws IOException { + return connect(new HttpRequests.RequestProcessor() { + @Override + public String process(@NotNull HttpRequests.Request request) throws IOException { + int contentLength = request.getConnection().getContentLength(); + BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(contentLength > 0 ? contentLength : 16 * 1024); + NetUtils.copyStreamContent(indicator, request.getInputStream(), out, contentLength); + return new String(out.getInternalBuffer(), 0, out.size(), HttpRequests.getCharset(request)); + } + }); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java index 88f3dfe8d43e..2e457f19dfc0 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java @@ -27,6 +27,7 @@ import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.io.HttpRequests; +import com.intellij.util.io.RequestBuilder; import com.intellij.util.io.URLUtil; import org.apache.http.client.utils.URIBuilder; import org.jetbrains.annotations.NotNull; @@ -102,7 +103,7 @@ public class RepositoryHelper { indicator.setText2(IdeBundle.message("progress.connecting.to.plugin.manager", uriBuilder.getHost())); } - HttpRequests.RequestBuilder request = HttpRequests.request(uriBuilder.toString()).forceHttps(forceHttps); + RequestBuilder request = HttpRequests.request(uriBuilder.toString()).forceHttps(forceHttps); return process(repositoryUrl, request.connect(new HttpRequests.RequestProcessor>() { @Override public List process(@NotNull HttpRequests.Request request) throws IOException { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/EditorOptionsTopHitProvider.java b/platform/platform-impl/src/com/intellij/ide/ui/EditorOptionsTopHitProvider.java index f528bca961b3..e6c53ec7db6d 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/EditorOptionsTopHitProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/EditorOptionsTopHitProvider.java @@ -16,6 +16,7 @@ package com.intellij.ide.ui; import com.intellij.ide.ui.search.BooleanOptionDescription; +import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.containers.ContainerUtil; @@ -37,7 +38,18 @@ public class EditorOptionsTopHitProvider extends OptionsTopHitProvider { ? "checkbox.enable.ctrl.mousewheel.changes.font.size.macos" : "checkbox.enable.ctrl.mousewheel.changes.font.size"), "IS_WHEEL_FONTCHANGE_ENABLED"), editor("Mouse: " + messageApp("checkbox.enable.drag.n.drop.functionality.in.editor"), "IS_DND_ENABLED"), - editor("Virtual Space: " + messageApp("checkbox.show.all.softwraps"), "IS_ALL_SOFTWRAPS_SHOWN"), + new EditorOptionDescription(null, messageApp("checkbox.show.softwraps.only.for.caret.line.action.text"), "preferences.editor") { + @Override + public boolean isOptionEnabled() { + return !EditorSettingsExternalizable.getInstance().isAllSoftWrapsShown(); + } + + @Override + public void setOptionState(boolean enabled) { + EditorSettingsExternalizable.getInstance().setAllSoftwrapsShown(!enabled); + fireUpdated(); + } + }, editor("Virtual Space: " + messageApp("checkbox.allow.placement.of.caret.after.end.of.line"), "IS_VIRTUAL_SPACE"), editor("Virtual Space: " + messageApp("checkbox.allow.placement.of.caret.inside.tabs"), "IS_CARET_INSIDE_TABS"), editor("Virtual Space: " + messageApp("checkbox.show.virtual.space.at.file.bottom"), "ADDITIONAL_PAGE_AT_BOTTOM"), diff --git a/platform/platform-impl/src/com/intellij/notification/impl/GotItStateKeeper.java b/platform/platform-impl/src/com/intellij/notification/impl/GotItStateKeeper.java deleted file mode 100644 index 8f2092b413d8..000000000000 --- a/platform/platform-impl/src/com/intellij/notification/impl/GotItStateKeeper.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2000-2014 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.notification.impl; - -import com.intellij.openapi.components.*; -import gnu.trove.THashSet; -import org.jdom.Element; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Set; - -@State( - name = GotItStateKeeper.COMPONENT_NAME, - storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/gotIt.xml", - roamingType = RoamingType.DISABLED) -) -public class GotItStateKeeper implements PersistentStateComponent { - public static final String COMPONENT_NAME = "GotItState"; - - private static final String ELEMENT_NAME = "disabledNotification"; - private static final String ATTRIBUTE_NAME = "key"; - - private final Set myDisabledNotifications = new THashSet(); - - public static GotItStateKeeper getInstance() { - return ServiceManager.getService(GotItStateKeeper.class); - } - - public synchronized boolean isNotificationDisabled(@NotNull String key) { - return myDisabledNotifications.contains(key); - } - - public synchronized void disableNotification(@NotNull String key) { - myDisabledNotifications.add(key); - } - - @Nullable - @Override - public synchronized Element getState() { - Element element = new Element(COMPONENT_NAME); - for (String key : myDisabledNotifications) { - Element child = new Element(ELEMENT_NAME); - child.setAttribute(ATTRIBUTE_NAME, key); - element.addContent(child); - } - return element; - } - - @Override - public synchronized void loadState(Element state) { - myDisabledNotifications.clear(); - for (Element child : state.getChildren(ELEMENT_NAME)) { - String key = child.getAttributeValue(ATTRIBUTE_NAME); - if (key != null) { - myDisabledNotifications.add(key); - } - } - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java b/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java index f57812afca18..88f74955f8e5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java @@ -15,11 +15,12 @@ */ package com.intellij.openapi.application.ex; +import com.intellij.openapi.components.impl.stores.DirectoryStorageData; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.io.URLUtil; import gnu.trove.THashMap; -import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -32,46 +33,33 @@ public class DecodeDefaultsUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.ex.DecodeDefaultsUtil"); private static final Map RESOURCE_CACHE = Collections.synchronizedMap(new THashMap()); - @NonNls private static final String XML_EXTENSION = ".xml"; - - public static URL getDefaults(Object requestor, final String componentResourcePath) { - if (RESOURCE_CACHE.containsKey(componentResourcePath)) { - return RESOURCE_CACHE.get(componentResourcePath); + public static URL getDefaults(Object requestor, @NotNull String componentResourcePath) { + URL url = RESOURCE_CACHE.get(componentResourcePath); + if (url == null) { + Class requestorClass = requestor.getClass(); + if (StringUtil.startsWithChar(componentResourcePath, '/')) { + url = requestorClass.getResource(componentResourcePath + DirectoryStorageData.DEFAULT_EXT); + } + else { + url = requestorClass.getResource('/' + ApplicationManagerEx.getApplicationEx().getName() + '/' + componentResourcePath + DirectoryStorageData.DEFAULT_EXT); + if (url == null) { + url = requestorClass.getResource('/' + componentResourcePath + DirectoryStorageData.DEFAULT_EXT); + } + } + RESOURCE_CACHE.put(componentResourcePath, url); } - - URL url = getDefaultsImpl(requestor, componentResourcePath); - RESOURCE_CACHE.put(componentResourcePath, url); return url; } - private static URL getDefaultsImpl(final Object requestor, final String componentResourcePath) { - boolean isPathAbsolute = StringUtil.startsWithChar(componentResourcePath, '/'); - if (isPathAbsolute) { - return requestor.getClass().getResource(componentResourcePath + XML_EXTENSION); - } - else { - return getResourceByRelativePath(requestor, componentResourcePath, XML_EXTENSION); - } - } - @Nullable - public static InputStream getDefaultsInputStream(Object requestor, final String componentResourcePath) { + public static InputStream getDefaultsInputStream(Object requestor, @NotNull String componentResourcePath) { try { final URL defaults = getDefaults(requestor, componentResourcePath); - return defaults != null ? URLUtil.openStream(defaults) : null; + return defaults == null ? null : URLUtil.openStream(defaults); } catch (IOException e) { LOG.error(e); return null; } } - - private static URL getResourceByRelativePath(Object requestor, final String componentResourcePath, String resourceExtension) { - String appName = ApplicationManagerEx.getApplicationEx().getName(); - URL result = requestor.getClass().getResource("/" + appName + "/" + componentResourcePath + resourceExtension); - if (result == null) { - result = requestor.getClass().getResource("/" + componentResourcePath + resourceExtension); - } - return result; - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java index 2b7e32717318..08bd9dbbab6b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java @@ -88,6 +88,7 @@ public class DummyProject extends UserDataHolderBase implements Project { return null; } + @Nullable @Override public String getBasePath() { return null; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java index 4d34e071993b..22ac3611ac82 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java @@ -18,7 +18,10 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.application.options.PathMacrosImpl; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.impl.ApplicationImpl; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.PathMacroManager; +import com.intellij.openapi.components.StateStorageOperation; +import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.NamedJDOMExternalizable; import com.intellij.openapi.vfs.LocalFileSystem; @@ -33,13 +36,11 @@ import java.io.IOException; class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationStore { private static final Logger LOG = Logger.getInstance(ApplicationStoreImpl.class); - private static final String XML_EXTENSION = ".xml"; - private static final String DEFAULT_STORAGE_SPEC = StoragePathMacros.APP_CONFIG + "/" + PathManager.DEFAULT_OPTIONS_FILE_NAME + XML_EXTENSION; + private static final String DEFAULT_STORAGE_SPEC = StoragePathMacros.APP_CONFIG + "/" + PathManager.DEFAULT_OPTIONS_FILE_NAME + DirectoryStorageData.DEFAULT_EXT; private static final String ROOT_ELEMENT_NAME = "application"; private final ApplicationImpl myApplication; private final StateStorageManager myStateStorageManager; - private final DefaultsStateStorage myDefaultsStateStorage; private String myConfigPath; @@ -59,7 +60,7 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto @Override protected String getOldStorageSpec(@NotNull Object component, @NotNull String componentName, @NotNull StateStorageOperation operation) { if (component instanceof NamedJDOMExternalizable) { - return StoragePathMacros.APP_CONFIG + "/" + ((NamedJDOMExternalizable)component).getExternalFileName() + XML_EXTENSION; + return StoragePathMacros.APP_CONFIG + '/' + ((NamedJDOMExternalizable)component).getExternalFileName() + DirectoryStorageData.DEFAULT_EXT; } else { return DEFAULT_STORAGE_SPEC; @@ -68,7 +69,7 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto @Override protected TrackingPathMacroSubstitutor getMacroSubstitutor(@NotNull final String fileSpec) { - if (fileSpec.equals(StoragePathMacros.APP_CONFIG + "/" + PathMacrosImpl.EXT_FILE_NAME + XML_EXTENSION)) return null; + if (fileSpec.equals(StoragePathMacros.APP_CONFIG + '/' + PathMacrosImpl.EXT_FILE_NAME + DirectoryStorageData.DEFAULT_EXT)) return null; return super.getMacroSubstitutor(fileSpec); } @@ -92,7 +93,6 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto } } }; - myDefaultsStateStorage = new DefaultsStateStorage(null); } @Override @@ -139,7 +139,7 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto @Nullable @Override - protected StateStorage getDefaultsStorage() { - return myDefaultsStateStorage; + protected PathMacroManager getPathMacroManagerForDefaults() { + return null; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java index de61848337a7..a4db00970e4a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java @@ -15,7 +15,9 @@ */ package com.intellij.openapi.components.impl.stores; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.PathMacroManager; +import com.intellij.openapi.components.PathMacroSubstitutor; +import com.intellij.openapi.components.StateStorageException; import com.intellij.openapi.project.impl.ProjectManagerImpl; import com.intellij.util.SmartList; import org.jdom.Element; @@ -34,18 +36,11 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl { private static final List ourConversionProblemsStorage = new SmartList(); - private final ComponentManager myComponentManager; - private final DefaultsStateStorage myDefaultsStateStorage; private StateStorageManager myStateStorageManager; + protected final PathMacroManager myPathMacroManager; - protected BaseFileConfigurableStoreImpl(@NotNull ComponentManager componentManager) { - myComponentManager = componentManager; - myDefaultsStateStorage = new DefaultsStateStorage(PathMacroManager.getInstance(myComponentManager)); - } - - @NotNull - public ComponentManager getComponentManager() { - return myComponentManager; + protected BaseFileConfigurableStoreImpl(@NotNull PathMacroManager pathMacroManager) { + myPathMacroManager = pathMacroManager; } protected static class BaseStorageData extends StorageData { @@ -115,10 +110,10 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl { return (BaseStorageData)getMainStorage().getStorageData(); } - @Nullable + @NotNull @Override - protected StateStorage getDefaultsStorage() { - return myDefaultsStateStorage; + protected final PathMacroManager getPathMacroManagerForDefaults() { + return myPathMacroManager; } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index a1ec60a41c54..72e4cea994d4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -16,6 +16,7 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.application.*; +import com.intellij.openapi.application.ex.DecodeDefaultsUtil; import com.intellij.openapi.components.*; import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.impl.ComponentManagerImpl; @@ -29,6 +30,7 @@ import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtilRt; @@ -37,12 +39,16 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.SmartHashSet; import com.intellij.util.messages.MessageBus; +import com.intellij.util.xmlb.JDOMXIncluder; import gnu.trove.THashMap; import org.jdom.Element; +import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.lang.reflect.Type; +import java.net.URL; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; @@ -52,9 +58,6 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { private final Map myComponents = Collections.synchronizedMap(new THashMap()); private final List mySettingsSavingComponents = new CopyOnWriteArrayList(); - @Nullable - protected abstract StateStorage getDefaultsStorage(); - @Override public void initComponent(@NotNull Object component, boolean service) { if (component instanceof SettingsSavingComponent) { @@ -158,7 +161,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { return; } - Element element = getJdomState(component, componentName, stateStorage); + Element element = stateStorage.getState(component, componentName, Element.class, null); if (element == null) { return; } @@ -185,30 +188,18 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { myComponents.put(componentName, component); } - private void loadJdomDefaults(@NotNull Object component, @NotNull String componentName) { + private void loadJdomDefaults(@NotNull JDOMExternalizable component, @NotNull String componentName) { try { - StateStorage defaultsStorage = getDefaultsStorage(); - if (defaultsStorage == null) { - return; + Element defaultState = getDefaultState(component, componentName, Element.class); + if (defaultState != null) { + component.readExternal(defaultState); } - - Element defaultState = getJdomState(component, componentName, defaultsStorage); - if (defaultState == null) { - return; - } - - ((JDOMExternalizable)component).readExternal(defaultState); } catch (Exception e) { LOG.error("Cannot load defaults for " + component.getClass(), e); } } - @Nullable - private static Element getJdomState(final Object component, @NotNull String componentName, @NotNull StateStorage defaultsStorage) { - return defaultsStorage.getState(component, componentName, Element.class, null); - } - @Nullable protected Project getProject() { return null; @@ -239,11 +230,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } Class stateClass = getComponentStateClass(component); - T state = null; - StateStorage defaultsStorage = getDefaultsStorage(); - if (defaultsStorage != null) { - state = defaultsStorage.getState(component, name, stateClass, null); - } + T state = getDefaultState(component, name, stateClass); Storage[] storageSpecs = getComponentStorageSpecs(component, stateSpec, StateStorageOperation.READ); for (Storage storageSpec : storageSpecs) { @@ -264,6 +251,34 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { return name; } + @Nullable + protected abstract PathMacroManager getPathMacroManagerForDefaults(); + + @Nullable + protected T getDefaultState(@NotNull Object component, @NotNull String componentName, @NotNull final Class stateClass) { + URL url = DecodeDefaultsUtil.getDefaults(component, componentName); + if (url == null) { + return null; + } + + try { + Element documentElement = JDOMXIncluder.resolve(JDOMUtil.loadDocument(url), url.toExternalForm()).detachRootElement(); + + PathMacroManager pathMacroManager = getPathMacroManagerForDefaults(); + if (pathMacroManager != null) { + pathMacroManager.expandPaths(documentElement); + } + + return DefaultStateSerializer.deserializeState(documentElement, stateClass, null); + } + catch (IOException e) { + throw new StateStorageException("Error loading state from " + url, e); + } + catch (JDOMException e) { + throw new StateStorageException("Error loading state from " + url, e); + } + } + @NotNull private static Class getComponentStateClass(@NotNull final PersistentStateComponent persistentStateComponent) { final Class persistentStateComponentClass = PersistentStateComponent.class; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 6cd6ea590b9d..2ffbd3da555d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -31,17 +31,14 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -//todo: extends from base store class public class DefaultProjectStoreImpl extends ProjectStoreImpl { - @Nullable private final Element myElement; private final ProjectManagerImpl myProjectManager; @NonNls private static final String ROOT_TAG_NAME = "defaultProject"; - public DefaultProjectStoreImpl(@NotNull ProjectImpl project, @NotNull ProjectManagerImpl projectManager) { - super(project); + public DefaultProjectStoreImpl(@NotNull ProjectImpl project, @NotNull ProjectManagerImpl projectManager, @NotNull PathMacroManager pathMacroManager) { + super(project, pathMacroManager); myProjectManager = projectManager; - myElement = projectManager.getDefaultProjectRootElement(); } @Nullable @@ -53,21 +50,12 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { @NotNull @Override protected StateStorageManager createStateStorageManager() { - Element _d = null; - - if (myElement != null) { - myElement.detach(); - _d = myElement; - } - - ComponentManager componentManager = getComponentManager(); - final Element element = _d; - final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, PathMacroManager.getInstance(componentManager).createTrackingSubstitutor(), + final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, myPathMacroManager.createTrackingSubstitutor(), ROOT_TAG_NAME, null) { @Override @Nullable protected Element loadLocalData() { - return element; + return myProjectManager.getDefaultProjectRootElement(); } @Override @@ -176,9 +164,10 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { } @Override - public void load() throws IOException, StateStorageException { - if (myElement == null) return; - super.load(); + public void load() throws IOException { + if (myProjectManager.getDefaultProjectRootElement() != null) { + super.load(); + } } private static class MyExternalizationSession implements StateStorageManager.ExternalizationSession { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java deleted file mode 100644 index a8170ea9fbfa..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.components.impl.stores; - -import com.intellij.openapi.application.ex.DecodeDefaultsUtil; -import com.intellij.openapi.components.PathMacroManager; -import com.intellij.openapi.components.StateStorage; -import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.xmlb.JDOMXIncluder; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.JDOMException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.net.URL; -import java.util.Collection; -import java.util.Set; - -class DefaultsStateStorage implements StateStorage { - private final PathMacroManager myPathMacroManager; - - public DefaultsStateStorage(@Nullable final PathMacroManager pathMacroManager) { - myPathMacroManager = pathMacroManager; - } - - @Nullable - private Element getState(final Object component, final String componentName) throws StateStorageException { - final URL url = DecodeDefaultsUtil.getDefaults(component, componentName); - if (url == null) { - return null; - } - - try { - Document document = JDOMUtil.loadDocument(url); - document = JDOMXIncluder.resolve(document, url.toExternalForm()); - final Element documentElement = document.detachRootElement(); - - if (myPathMacroManager != null) { - myPathMacroManager.expandPaths(documentElement); - } - - return documentElement; - } - catch (IOException e) { - throw new StateStorageException("Error loading state from " + url, e); - } - catch (JDOMException e) { - throw new StateStorageException("Error loading state from " + url, e); - } - } - - @Override - @Nullable - public T getState(final Object component, @NotNull final String componentName, @NotNull final Class stateClass, @Nullable final T mergeInto) { - return DefaultStateSerializer.deserializeState(getState(component, componentName), stateClass, mergeInto); - } - - @Override - public boolean hasState(@Nullable final Object component, @NotNull final String componentName, final Class aClass, final boolean reloadData) { - return DecodeDefaultsUtil.getDefaults(component, componentName) != null; - } - - @Override - @Nullable - public ExternalizationSession startExternalization() { - return null; - } - - @Override - public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection changedFiles, @NotNull Set result) { - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java index 08572a0599cc..404512c9f34a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java @@ -63,8 +63,8 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject private StorageScheme myScheme = StorageScheme.DEFAULT; private String myPresentableUrl; - ProjectStoreImpl(@NotNull ProjectImpl project) { - super(project); + ProjectStoreImpl(@NotNull ProjectImpl project, @NotNull PathMacroManager pathMacroManager) { + super(pathMacroManager); myProject = project; } @@ -359,16 +359,12 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } @Override - public void loadProjectFromTemplate(@NotNull final ProjectImpl defaultProject) { - XmlElementStorage stateStorage = getProjectFileStorage(); - + public void loadProjectFromTemplate(@NotNull ProjectImpl defaultProject) { defaultProject.save(); - final IProjectStore projectStore = defaultProject.getStateStore(); - assert projectStore instanceof DefaultProjectStoreImpl; - DefaultProjectStoreImpl defaultProjectStore = (DefaultProjectStoreImpl)projectStore; - final Element element = defaultProjectStore.getStateCopy(); + + Element element = ((DefaultProjectStoreImpl)defaultProject.getStateStore()).getStateCopy(); if (element != null) { - stateStorage.setDefaultState(element); + getProjectFileStorage().setDefaultState(element); } } @@ -387,7 +383,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject @NotNull @Override protected StateStorageManager createStateStorageManager() { - return new ProjectStateStorageManager(PathMacroManager.getInstance(getComponentManager()).createTrackingSubstitutor(), myProject); + return new ProjectStateStorageManager(myPathMacroManager.createTrackingSubstitutor(), myProject); } static class ProjectStorageData extends BaseStorageData { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentBoundRenderer.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentBoundRenderer.java index b179b7d4dd0a..f2ac5b7545cc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentBoundRenderer.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentBoundRenderer.java @@ -155,25 +155,36 @@ public class FragmentBoundRenderer implements LineMarkerRenderer, LineSeparatorR final boolean mirrorX, final int mirrorSize) { final Iterator> iterator = points.iterator(); assert iterator.hasNext(); - final Convertor c = new Convertor() { - @Override - public Integer convert(Integer o) { - final int val = x1 + o - subtractX; - if (mirrorX) { - return mirrorSize - val; - } - return val; - } - }; + + int[] xPoints = new int[points.size()]; + int[] yPoints1 = new int[points.size()]; + int[] yPoints2 = new int[points.size()]; + int n = 0; + Couple previous = iterator.next(); while (iterator.hasNext()) { final Couple next = iterator.next(); - UIUtil.drawLine(g, c.convert(previous.getFirst()), y + offset + previous.getSecond() - myLineHeight/2, c.convert(next.getFirst()), - y + offset + next.getSecond() - myLineHeight/2); - UIUtil.drawLine(g, c.convert(previous.getFirst()), y - offset + previous.getSecond() - myLineHeight/2, c.convert(next.getFirst()), - y - offset + next.getSecond() - myLineHeight/2); + + xPoints[n] = convert(previous.getFirst(), x1, subtractX, mirrorX, mirrorSize); + yPoints1[n] = y + offset + previous.getSecond() - myLineHeight / 2; + yPoints2[n] = y - offset + previous.getSecond() - myLineHeight / 2; + n++; previous = next; } + xPoints[n] = convert(previous.getFirst(), x1, subtractX, mirrorX, mirrorSize); + yPoints1[n] = y + offset + previous.getSecond() - myLineHeight / 2; + yPoints2[n] = y - offset + previous.getSecond() - myLineHeight / 2; + + g.drawPolyline(xPoints, yPoints1, points.size()); + g.drawPolyline(xPoints, yPoints2, points.size()); + } + + private static int convert(int value, int x1, int subtractX, boolean mirrorX, int mirrorSize) { + final int val = x1 + value - subtractX; + if (mirrorX) { + return mirrorSize - val; + } + return val; } private static class ShoeneLine { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java index 2605c4f74852..876018fe447e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java @@ -19,6 +19,8 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.util.Key; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; +import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,6 +49,18 @@ abstract class FoldRegionsTree { }; private static final Comparator BY_END_OFFSET_REVERSE = Collections.reverseOrder(BY_END_OFFSET); + private static final TObjectHashingStrategy OFFSET_BASED_HASHING_STRATEGY = new TObjectHashingStrategy() { + @Override + public int computeHashCode(FoldRegion o) { + return o.getStartOffset() * 31 + o.getEndOffset(); + } + + @Override + public boolean equals(FoldRegion o1, FoldRegion o2) { + return o1.getStartOffset() == o2.getStartOffset() && o1.getEndOffset() == o2.getEndOffset(); + } + }; + void clear() { clearCachedValues(); @@ -67,11 +81,16 @@ abstract class FoldRegionsTree { List topLevels = new ArrayList(myRegions.size() / 2); List visible = new ArrayList(myRegions.size()); List allValid = new ArrayList(myRegions.size()); + Set distinctRegions = new THashSet(myRegions.size(), OFFSET_BASED_HASHING_STRATEGY); FoldRegion currentCollapsed = null; for (FoldRegion region : myRegions) { if (!region.isValid()) { continue; } + if (!distinctRegions.add(region)) { + region.dispose(); + continue; + } allValid.add(region); } @@ -134,9 +153,11 @@ abstract class FoldRegionsTree { rebuild(); return; } + + Set distinctRegions = new THashSet(visibleRegions.length, OFFSET_BASED_HASHING_STRATEGY); for (FoldRegion foldRegion : visibleRegions) { - if (!foldRegion.isValid()) { + if (!foldRegion.isValid() || !distinctRegions.add(foldRegion)) { rebuild(); return; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ForcedSoftWrapsNotificationProvider.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ForcedSoftWrapsNotificationProvider.java index a89a42e2803d..9d9004ad6cd2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ForcedSoftWrapsNotificationProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ForcedSoftWrapsNotificationProvider.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.editor.impl; -import com.intellij.notification.impl.GotItStateKeeper; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorBundle; import com.intellij.openapi.fileEditor.FileEditor; @@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable; public class ForcedSoftWrapsNotificationProvider extends EditorNotifications.Provider { private static final Key KEY = Key.create("forced.soft.wraps.notification.panel"); - private static final String GOT_IT_KEY = "Forced soft wraps in editor"; + private static final String DISABLED_NOTIFICATION_KEY = "disable.forced.soft.wraps.notification"; @NotNull @Override @@ -46,7 +46,7 @@ public class ForcedSoftWrapsNotificationProvider extends EditorNotifications.Pro final Project project = editor.getProject(); if (project == null || !Boolean.TRUE.equals(editor.getUserData(EditorImpl.FORCED_SOFT_WRAPS)) - || GotItStateKeeper.getInstance().isNotificationDisabled(GOT_IT_KEY)) return null; + || PropertiesComponent.getInstance().isTrueValue(DISABLED_NOTIFICATION_KEY)) return null; final EditorNotificationPanel panel = new EditorNotificationPanel(); panel.setText(EditorBundle.message("forced.soft.wrap.message")); @@ -60,7 +60,7 @@ public class ForcedSoftWrapsNotificationProvider extends EditorNotifications.Pro panel.createActionLabel(EditorBundle.message("forced.soft.wrap.dont.show.again.message"), new Runnable() { @Override public void run() { - GotItStateKeeper.getInstance().disableNotification(GOT_IT_KEY); + PropertiesComponent.getInstance().setValue(DISABLED_NOTIFICATION_KEY, "true"); EditorNotifications.getInstance(project).updateAllNotifications(); } }); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 6bc28ed89ce2..a24422aa64ba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -395,6 +395,7 @@ public class SoftWrapApplianceManager implements Dumpable { if (myContext.delayedSoftWrap != null) { myStorage.remove(myContext.delayedSoftWrap); + myContext.delayedSoftWrap = null; } if (softWrap == null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java deleted file mode 100644 index e9e1968b37d1..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.intellij.openapi.fileEditor.impl; - -import com.intellij.util.ui.UIUtil; - -import java.awt.*; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ImageObserver; -import java.awt.image.RenderedImage; -import java.awt.image.renderable.RenderableImage; -import java.text.AttributedCharacterIterator; -import java.util.Map; - -/** - * @author max - */ -public class WaverGraphicsDecorator extends Graphics2D { - public static int WAVE_ALPHA_KEY = 0xFE; - private final Graphics2D myOriginal; - private final Color myWaveColor; - - public WaverGraphicsDecorator(final Graphics2D original, final Color waveColor) { - myOriginal = original; - myWaveColor = waveColor; - } - - private void drawWave(String text, int offset, int baseline) { - Color fore = getColor(); - if (fore.getAlpha() == WAVE_ALPHA_KEY) { - int width = getFontMetrics().stringWidth(text); - setColor(myWaveColor); - final int wavedAt = baseline + 1; - for (int x = offset; x < offset + width; x += 4) { - UIUtil.drawLine(this, x, wavedAt, x + 2, wavedAt + 2); - UIUtil.drawLine(this, x + 3, wavedAt + 1, x + 4, wavedAt); - } - setColor(fore); - } - } - - @Override - public void draw(final Shape s) { - myOriginal.draw(s); - } - - @Override - public boolean drawImage(final Image img, final AffineTransform xform, final ImageObserver obs) { - return myOriginal.drawImage(img, xform, obs); - } - - @Override - public void drawImage(final BufferedImage img, final BufferedImageOp op, final int x, final int y) { - myOriginal.drawImage(img, op, x, y); - } - - @Override - public void drawRenderedImage(final RenderedImage img, final AffineTransform xform) { - myOriginal.drawRenderedImage(img, xform); - } - - @Override - public void drawRenderableImage(final RenderableImage img, final AffineTransform xform) { - myOriginal.drawRenderableImage(img, xform); - } - - @Override - public void drawString(final String str, final int x, final int y) { - myOriginal.drawString(str, x, y); - drawWave(str, x, y); - } - - @Override - public void drawString(final String s, final float x, final float y) { - myOriginal.drawString(s, x, y); - drawWave(s, (int)x, (int)y); - } - - @Override - public void drawString(final AttributedCharacterIterator iterator, final int x, final int y) { - myOriginal.drawString(iterator, x, y); - //TODO: drawWave - } - - @Override - public void drawString(final AttributedCharacterIterator iterator, final float x, final float y) { - myOriginal.drawString(iterator, x, y); - //TODO: drawWave - } - - @Override - public void drawGlyphVector(final GlyphVector g, final float x, final float y) { - myOriginal.drawGlyphVector(g, x, y); - //TODO: drawWave - } - - @Override - public void fill(final Shape s) { - myOriginal.fill(s); - } - - @Override - public boolean hit(final Rectangle rect, final Shape s, final boolean onStroke) { - return myOriginal.hit(rect, s, onStroke); - } - - @Override - public GraphicsConfiguration getDeviceConfiguration() { - return myOriginal.getDeviceConfiguration(); - } - - @Override - public void setComposite(final Composite comp) { - myOriginal.setComposite(comp); - } - - @Override - public void setPaint(final Paint paint) { - myOriginal.setPaint(paint); - } - - @Override - public void setStroke(final Stroke s) { - myOriginal.setStroke(s); - } - - @Override - public void setRenderingHint(final RenderingHints.Key hintKey, final Object hintValue) { - myOriginal.setRenderingHint(hintKey, hintValue); - } - - @Override - public Object getRenderingHint(final RenderingHints.Key hintKey) { - return myOriginal.getRenderingHint(hintKey); - } - - @Override - public void setRenderingHints(final Map hints) { - myOriginal.setRenderingHints(hints); - } - - @Override - public void addRenderingHints(final Map hints) { - myOriginal.addRenderingHints(hints); - } - - @Override - public RenderingHints getRenderingHints() { - return myOriginal.getRenderingHints(); - } - - @Override - public void translate(final int x, final int y) { - myOriginal.translate(x, y); - } - - @Override - public void translate(final double tx, final double ty) { - myOriginal.translate(tx, ty); - } - - @Override - public void rotate(final double theta) { - myOriginal.rotate(theta); - } - - @Override - public void rotate(final double theta, final double x, final double y) { - myOriginal.rotate(theta, x, y); - } - - @Override - public void scale(final double sx, final double sy) { - myOriginal.scale(sx, sy); - } - - @Override - public void shear(final double shx, final double shy) { - myOriginal.shear(shx, shy); - } - - @Override - public void transform(final AffineTransform Tx) { - myOriginal.transform(Tx); - } - - @Override - public void setTransform(final AffineTransform Tx) { - myOriginal.setTransform(Tx); - } - - @Override - public AffineTransform getTransform() { - return myOriginal.getTransform(); - } - - @Override - public Paint getPaint() { - return myOriginal.getPaint(); - } - - @Override - public Composite getComposite() { - return myOriginal.getComposite(); - } - - @Override - public void setBackground(final Color color) { - myOriginal.setBackground(color); - } - - @Override - public Color getBackground() { - return myOriginal.getBackground(); - } - - @Override - public Stroke getStroke() { - return myOriginal.getStroke(); - } - - @Override - public void clip(final Shape s) { - myOriginal.clip(s); - } - - @Override - public FontRenderContext getFontRenderContext() { - return myOriginal.getFontRenderContext(); - } - - @Override - public Graphics create() { - return new WaverGraphicsDecorator((Graphics2D)myOriginal.create(), myWaveColor); - } - - @Override - public Color getColor() { - return myOriginal.getColor(); - } - - @Override - public void setColor(final Color c) { - myOriginal.setColor(c); - } - - @Override - public void setPaintMode() { - myOriginal.setPaintMode(); - } - - @Override - public void setXORMode(final Color c1) { - myOriginal.setXORMode(c1); - } - - @Override - public Font getFont() { - return myOriginal.getFont(); - } - - @Override - public void setFont(final Font font) { - myOriginal.setFont(font); - } - - @Override - public FontMetrics getFontMetrics(final Font f) { - return myOriginal.getFontMetrics(f); - } - - @Override - public Rectangle getClipBounds() { - return myOriginal.getClipBounds(); - } - - @Override - public void clipRect(final int x, final int y, final int width, final int height) { - myOriginal.clipRect(x, y, width, height); - } - - @Override - public void setClip(final int x, final int y, final int width, final int height) { - myOriginal.setClip(x, y, width, height); - } - - @Override - public Shape getClip() { - return myOriginal.getClip(); - } - - @Override - public void setClip(final Shape clip) { - myOriginal.setClip(clip); - } - - @Override - public void copyArea(final int x, final int y, final int width, final int height, final int dx, final int dy) { - myOriginal.copyArea(x, y, width, height, dx, dy); - } - - @Override - public void drawLine(final int x1, final int y1, final int x2, final int y2) { - myOriginal.drawLine(x1, y1, x2, y2); - } - - @Override - public void fillRect(final int x, final int y, final int width, final int height) { - myOriginal.fillRect(x, y, width, height); - } - - @Override - public void clearRect(final int x, final int y, final int width, final int height) { - myOriginal.clearRect(x, y, width, height); - } - - @Override - public void drawRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { - myOriginal.drawRoundRect(x, y, width, height, arcWidth, arcHeight); - } - - @Override - public void fillRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { - myOriginal.fillRoundRect(x, y, width, height, arcWidth, arcHeight); - } - - @Override - public void drawOval(final int x, final int y, final int width, final int height) { - myOriginal.drawOval(x, y, width, height); - } - - @Override - public void fillOval(final int x, final int y, final int width, final int height) { - myOriginal.fillOval(x, y, width, height); - } - - @Override - public void drawArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { - myOriginal.drawArc(x, y, width, height, startAngle, arcAngle); - } - - @Override - public void fillArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { - myOriginal.fillArc(x, y, width, height, startAngle, arcAngle); - } - - @Override - public void drawPolyline(final int[] xPoints, final int[] yPoints, final int nPoints) { - myOriginal.drawPolyline(xPoints, yPoints, nPoints); - } - - @Override - public void drawPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { - myOriginal.drawPolygon(xPoints, yPoints, nPoints); - } - - @Override - public void fillPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { - myOriginal.fillPolygon(xPoints, yPoints, nPoints); - } - - @Override - public boolean drawImage(final Image img, final int x, final int y, final ImageObserver observer) { - return myOriginal.drawImage(img, x, y, observer); - } - - @Override - public boolean drawImage(final Image img, final int x, final int y, final int width, final int height, final ImageObserver observer) { - return myOriginal.drawImage(img, x, y, width, height, observer); - } - - @Override - public boolean drawImage(final Image img, final int x, final int y, final Color bgcolor, final ImageObserver observer) { - return myOriginal.drawImage(img, x, y, bgcolor, observer); - } - - @Override - public boolean drawImage(final Image img, - final int x, - final int y, - final int width, - final int height, - final Color bgcolor, - final ImageObserver observer) { - return myOriginal.drawImage(img, x, y, width, height, bgcolor, observer); - } - - @Override - public boolean drawImage(final Image img, - final int dx1, - final int dy1, - final int dx2, - final int dy2, - final int sx1, - final int sy1, - final int sx2, - final int sy2, - final ImageObserver observer) { - return myOriginal.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); - } - - @Override - public boolean drawImage(final Image img, - final int dx1, - final int dy1, - final int dx2, - final int dy2, - final int sx1, - final int sy1, - final int sx2, - final int sy2, - final Color bgcolor, - final ImageObserver observer) { - return myOriginal.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer); - } - - @Override - public void dispose() { - //myOriginal.dispose(); - } - - - @Override - public Rectangle getClipRect() { - return myOriginal.getClipRect(); - } - - @Override - public boolean hitClip(final int x, final int y, final int width, final int height) { - return myOriginal.hitClip(x, y, width, height); - } - - @Override - public Rectangle getClipBounds(final Rectangle r) { - return myOriginal.getClipBounds(r); - } - - @Override - public void fill3DRect(final int x, final int y, final int width, final int height, final boolean raised) { - myOriginal.fill3DRect(x, y, width, height, raised); - } - - @Override - public void draw3DRect(final int x, final int y, final int width, final int height, final boolean raised) { - myOriginal.draw3DRect(x, y, width, height, raised); - } - - @Override - public Graphics create(final int x, final int y, final int width, final int height) { - return new WaverGraphicsDecorator((Graphics2D)myOriginal.create(x, y, width, height), myWaveColor); - } - - @Override - public void drawRect(final int x, final int y, final int width, final int height) { - myOriginal.drawRect(x, y, width, height); - } - - @Override - public void drawPolygon(final Polygon p) { - myOriginal.drawPolygon(p); - } - - @Override - public void fillPolygon(final Polygon p) { - myOriginal.fillPolygon(p); - } - - @Override - public FontMetrics getFontMetrics() { - return myOriginal.getFontMetrics(); - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java index 14f0c95ec31b..67d7004e4874 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java @@ -20,7 +20,6 @@ import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; @@ -32,7 +31,6 @@ import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.psi.SingleRootFileViewProvider; @@ -63,8 +61,6 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware { @NonNls private static final String SELECTION_END_LINE_ATTR = "selection-end-line"; @NonNls private static final String SELECTION_END_COLUMN_ATTR = "selection-end-column"; @NonNls private static final String VERTICAL_SCROLL_PROPORTION_ATTR = "vertical-scroll-proportion"; - @NonNls private static final String VERTICAL_OFFSET_ATTR = "vertical-offset"; - @NonNls private static final String MAX_VERTICAL_OFFSET_ATTR = "max-vertical-offset"; @NonNls private static final String CARET_ELEMENT = "caret"; public static TextEditorProvider getInstance() { @@ -115,12 +111,6 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware { String verticalScrollProportion = element.getAttributeValue(VERTICAL_SCROLL_PROPORTION_ATTR); state.VERTICAL_SCROLL_PROPORTION = verticalScrollProportion == null ? 0 : Float.parseFloat(verticalScrollProportion); - String verticalOffset = element.getAttributeValue(VERTICAL_OFFSET_ATTR); - String maxVerticalOffset = element.getAttributeValue(MAX_VERTICAL_OFFSET_ATTR); - if (!StringUtil.isEmpty(verticalOffset) && !StringUtil.isEmpty(maxVerticalOffset)) { - state.VERTICAL_SCROLL_OFFSET = Integer.parseInt(verticalOffset); - state.MAX_VERTICAL_SCROLL_OFFSET = Integer.parseInt(maxVerticalOffset); - } } catch (NumberFormatException ignored) { } @@ -149,8 +139,6 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware { TextEditorState state = (TextEditorState)_state; element.setAttribute(VERTICAL_SCROLL_PROPORTION_ATTR, Float.toString(state.VERTICAL_SCROLL_PROPORTION)); - element.setAttribute(VERTICAL_OFFSET_ATTR, Integer.toString(state.VERTICAL_SCROLL_OFFSET)); - element.setAttribute(MAX_VERTICAL_OFFSET_ATTR, Integer.toString(state.MAX_VERTICAL_SCROLL_OFFSET)); if (state.CARETS != null) { for (TextEditorState.CaretState caretState : state.CARETS) { Element e = new Element(CARET_ELEMENT); @@ -249,11 +237,6 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware { // Saving scrolling proportion on UNDO may cause undesirable results of undo action fails to perform since // scrolling proportion restored slightly differs from what have been saved. state.VERTICAL_SCROLL_PROPORTION = level == FileEditorStateLevel.UNDO ? -1 : EditorUtil.calcVerticalScrollProportion(editor); - if (editor instanceof EditorEx) { - state.VERTICAL_SCROLL_OFFSET = editor.getScrollingModel().getVerticalScrollOffset(); - JScrollBar scrollBar = ((EditorEx)editor).getScrollPane().getVerticalScrollBar(); - state.MAX_VERTICAL_SCROLL_OFFSET = scrollBar == null ? 0 : scrollBar.getMaximum(); - } return state; } @@ -295,21 +278,9 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware { editor.getSelectionModel().removeSelection(); } } - EditorEx editorEx = editor instanceof EditorEx ? (EditorEx)editor : null; - boolean preciselyScrollVertically = - state.VERTICAL_SCROLL_OFFSET > 0 - && editorEx != null - && editorEx.getScrollPane().getVerticalScrollBar() != null - && editorEx.getScrollPane().getVerticalScrollBar().getMaximum() == state.MAX_VERTICAL_SCROLL_OFFSET; - if (preciselyScrollVertically) { - editor.getScrollingModel().scrollVertically(state.VERTICAL_SCROLL_OFFSET); - } - else { - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - if (state.VERTICAL_SCROLL_PROPORTION != -1) { - EditorUtil.setVerticalScrollProportion(editor, state.VERTICAL_SCROLL_PROPORTION); - } + if (state.VERTICAL_SCROLL_PROPORTION != -1) { + EditorUtil.setVerticalScrollProportion(editor, state.VERTICAL_SCROLL_PROPORTION); } if (!editor.getCaretModel().supportsMultipleCarets()) { @@ -323,9 +294,7 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware { editor.getSelectionModel().setSelection(startOffset, endOffset); } } - if (!preciselyScrollVertically) { - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - } + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } protected class EditorWrapper extends UserDataHolderBase implements TextEditor { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java index d4aca486c041..f8d176533f06 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java @@ -32,8 +32,6 @@ public final class TextEditorState implements FileEditorState { public CaretState[] CARETS; public float VERTICAL_SCROLL_PROPORTION; - public int VERTICAL_SCROLL_OFFSET; - public int MAX_VERTICAL_SCROLL_OFFSET; /** * State which describes how editor is folded. diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index 6ab2ac759d83..1a0e16dfc640 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -238,6 +238,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project return getStateStore().getProjectBaseDir(); } + @Nullable @Override public String getBasePath() { return getStateStore().getProjectBasePath(); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 4988155eea4b..042730508909 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -94,6 +94,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt private ProjectImpl myDefaultProject; // Only used asynchronously in save and dispose, which itself are synchronized. @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private Element myDefaultProjectRootElement; // Only used asynchronously in save and dispose, which itself are synchronized. + private boolean myDefaultProjectConfigurationChanged; private final List myOpenProjects = new ArrayList(); private Project[] myOpenProjectsArrayCache = {}; @@ -257,6 +258,18 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt } } + File projectFile = new File(filePath); + if (projectFile.isFile()) { + FileUtil.delete(projectFile); + } + else { + File[] files = new File(projectFile, Project.DIRECTORY_STORE_FOLDER).listFiles(); + if (files != null) { + for (File file : files) { + FileUtil.delete(file); + } + } + } ProjectImpl project = createProject(projectName, filePath, false, optimiseTestLoadSpeed); try { initProject(project, useDefaultProjectSettings ? (ProjectImpl)getDefaultProject() : null); @@ -387,7 +400,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt try { myDefaultProject = createProject(null, "", true, ApplicationManager.getApplication().isUnitTestMode()); initProject(myDefaultProject, null); - myDefaultProjectRootElement = null; } catch (Throwable t) { PluginManager.processException(t); @@ -990,7 +1002,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt myDefaultProject.save(); } - if (myDefaultProjectRootElement == null) { + if (!myDefaultProjectConfigurationChanged) { // we are not ready to save return null; } @@ -1007,10 +1019,12 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt if (myDefaultProjectRootElement != null) { myDefaultProjectRootElement.detach(); } + myDefaultProjectConfigurationChanged = false; } public void setDefaultProjectRootElement(@NotNull Element defaultProjectRootElement) { myDefaultProjectRootElement = defaultProjectRootElement; + myDefaultProjectConfigurationChanged = true; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java index 1ee07d2fcab8..80b8c78f10e9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java @@ -60,7 +60,7 @@ public class DefaultRemoteContentProvider extends RemoteContentProvider { try { HttpRequests.request(url.toExternalForm()) .connectTimeout(60 * 1000) - .userAgent() + .productNameAsUserAgent() .hostNameVerifier(CertificateManager.HOSTNAME_VERIFIER) .connect(new HttpRequests.RequestProcessor() { @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index 9ed819cdd1aa..51ded3f9e4cb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -32,7 +32,6 @@ import com.intellij.openapi.vfs.newvfs.RefreshQueue; import com.intellij.openapi.vfs.newvfs.VfsImplUtil; import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile; import com.intellij.util.ArrayUtil; -import com.intellij.util.PathUtil; import com.intellij.util.Processor; import com.intellij.util.ThrowableConsumer; import com.intellij.util.containers.ContainerUtil; @@ -341,19 +340,12 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { return false; } - private void auxNotifyCompleted(@NotNull ThrowableConsumer consumer) { - for (LocalFileOperationsHandler handler : myHandlers) { - handler.afterDone(consumer); - } - } - - @Nullable - private File auxCopy(@NotNull VirtualFile file, @NotNull VirtualFile toDir, @NotNull String copyName) throws IOException { + private boolean auxCopy(@NotNull VirtualFile file, @NotNull VirtualFile toDir, @NotNull String copyName) throws IOException { for (LocalFileOperationsHandler handler : myHandlers) { final File copy = handler.copy(file, toDir, copyName); - if (copy != null) return copy; + if (copy != null) return true; } - return null; + return false; } private boolean auxRename(@NotNull VirtualFile file, @NotNull String newName) throws IOException { @@ -377,53 +369,97 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { return false; } - private static void delete(@NotNull File physicalFile) throws IOException { - if (!FileUtil.delete(physicalFile)) { - throw new IOException(VfsBundle.message("file.delete.error", physicalFile.getPath())); + private void auxNotifyCompleted(@NotNull ThrowableConsumer consumer) { + for (LocalFileOperationsHandler handler : myHandlers) { + handler.afterDone(consumer); } } @Override @NotNull - public VirtualFile createChildDirectory(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String dir) throws IOException { - final File ioDir = new File(convertToIOFile(parent), dir); - final boolean succeed = auxCreateDirectory(parent, dir) || ioDir.mkdirs(); + public VirtualFile createChildDirectory(Object requestor, @NotNull final VirtualFile parent, @NotNull final String dir) throws IOException { + if (!VirtualFile.isValidName(dir)) { + throw new IOException(VfsBundle.message("directory.invalid.name.error", dir)); + } + + if (!parent.exists() || !parent.isDirectory()) { + throw new IOException(VfsBundle.message("vfs.target.not.directory.error", parent.getPath())); + } + if (parent.findChild(dir) != null) { + throw new IOException(VfsBundle.message("vfs.target.already.exists.error", parent.getPath() + "/" + dir)); + } + + File ioParent = convertToIOFile(parent); + if (!ioParent.isDirectory()) { + throw new IOException(VfsBundle.message("target.not.directory.error", ioParent.getPath())); + } + + if (!auxCreateDirectory(parent, dir)) { + File ioDir = new File(ioParent, dir); + if (!(ioDir.mkdirs() || ioDir.isDirectory())) { + throw new IOException(VfsBundle.message("new.directory.failed.error", ioDir.getPath())); + } + } + auxNotifyCompleted(new ThrowableConsumer() { @Override public void consume(LocalFileOperationsHandler handler) throws IOException { handler.createDirectory(parent, dir); } }); - if (!succeed) { - throw new IOException("Failed to create directory: " + ioDir.getPath()); - } return new FakeVirtualFile(parent, dir); } @NotNull @Override - public VirtualFile createChildFile(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String file) throws IOException { - final File ioFile = new File(convertToIOFile(parent), file); - final boolean succeed = auxCreateFile(parent, file) || FileUtil.createIfDoesntExist(ioFile); + public VirtualFile createChildFile(Object requestor, @NotNull final VirtualFile parent, @NotNull final String file) throws IOException { + if (!VirtualFile.isValidName(file)) { + throw new IOException(VfsBundle.message("file.invalid.name.error", file)); + } + + if (!parent.exists() || !parent.isDirectory()) { + throw new IOException(VfsBundle.message("vfs.target.not.directory.error", parent.getPath())); + } + if (parent.findChild(file) != null) { + throw new IOException(VfsBundle.message("vfs.target.already.exists.error", parent.getPath() + "/" + file)); + } + + File ioParent = convertToIOFile(parent); + if (!ioParent.isDirectory()) { + throw new IOException(VfsBundle.message("target.not.directory.error", ioParent.getPath())); + } + + if (!auxCreateFile(parent, file)) { + File ioFile = new File(ioParent, file); + if (!FileUtil.createIfDoesntExist(ioFile)) { + throw new IOException(VfsBundle.message("new.file.failed.error", ioFile.getPath())); + } + } + auxNotifyCompleted(new ThrowableConsumer() { @Override public void consume(LocalFileOperationsHandler handler) throws IOException { handler.createFile(parent, file); } }); - if (!succeed) { - throw new IOException("Failed to create child file at " + ioFile.getPath()); - } return new FakeVirtualFile(parent, file); } @Override - public void deleteFile(final Object requestor, @NotNull final VirtualFile file) throws IOException { - if (!auxDelete(file)) { - delete(convertToIOFile(file)); + public void deleteFile(Object requestor, @NotNull final VirtualFile file) throws IOException { + if (file.getParent() == null) { + throw new IOException(VfsBundle.message("cannot.delete.root.directory", file.getPath())); } + + if (!auxDelete(file)) { + File ioFile = convertToIOFile(file); + if (!FileUtil.delete(ioFile)) { + throw new IOException(VfsBundle.message("delete.failed.error", ioFile.getPath())); + } + } + auxNotifyCompleted(new ThrowableConsumer() { @Override public void consume(LocalFileOperationsHandler handler) throws IOException { @@ -484,17 +520,41 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { } @Override - public void moveFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent) throws IOException { + public void moveFile(Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent) throws IOException { + String name = file.getName(); + + if (!file.exists()) { + throw new IOException(VfsBundle.message("vfs.file.not.exist.error", file.getPath())); + } + if (file.getParent() == null) { + throw new IOException(VfsBundle.message("cannot.rename.root.directory", file.getPath())); + } + if (!newParent.exists() || !newParent.isDirectory()) { + throw new IOException(VfsBundle.message("vfs.target.not.directory.error", newParent.getPath())); + } + if (newParent.findChild(name) != null) { + throw new IOException(VfsBundle.message("vfs.target.already.exists.error", newParent.getPath() + "/" + name)); + } + + File ioFile = convertToIOFile(file); + if (!ioFile.exists()) { + throw new FileNotFoundException(VfsBundle.message("file.not.exist.error", ioFile.getPath())); + } + File ioParent = convertToIOFile(newParent); + if (!ioParent.isDirectory()) { + throw new IOException(VfsBundle.message("target.not.directory.error", ioParent.getPath())); + } + File ioTarget = new File(ioParent, name); + if (ioTarget.exists()) { + throw new IOException(VfsBundle.message("target.already.exists.error", ioTarget.getPath())); + } + if (!auxMove(file, newParent)) { - final File ioFrom = convertToIOFile(file); - final File ioParent = convertToIOFile(newParent); - if (!ioParent.isDirectory()) { - throw new IOException("Target '" + ioParent + "' is not a directory"); - } - if (!ioFrom.renameTo(new File(ioParent, file.getName()))) { - throw new IOException("Move failed: '" + file.getPath() + "' to '" + newParent.getPath() +"'"); + if (!ioFile.renameTo(ioTarget)) { + throw new IOException(VfsBundle.message("move.failed.error", ioFile.getPath(), ioParent.getPath())); } } + auxNotifyCompleted(new ThrowableConsumer() { @Override public void consume(LocalFileOperationsHandler handler) throws IOException { @@ -504,24 +564,39 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { } @Override - public void renameFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) throws IOException { - if (!file.exists()) { - throw new IOException("File to move does not exist: " + file.getPath()); + public void renameFile(Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) throws IOException { + if (!VirtualFile.isValidName(newName)) { + throw new IOException(VfsBundle.message("file.invalid.name.error", newName)); } - final VirtualFile parent = file.getParent(); - assert parent != null; + boolean sameName = !isCaseSensitive() && newName.equalsIgnoreCase(file.getName()); + + if (!file.exists()) { + throw new IOException(VfsBundle.message("vfs.file.not.exist.error", file.getPath())); + } + VirtualFile parent = file.getParent(); + if (parent == null) { + throw new IOException(VfsBundle.message("cannot.rename.root.directory", file.getPath())); + } + if (!sameName && parent.findChild(newName) != null) { + throw new IOException(VfsBundle.message("vfs.target.already.exists.error", parent.getPath() + "/" + newName)); + } + + File ioFile = convertToIOFile(file); + if (!ioFile.exists()) { + throw new FileNotFoundException(VfsBundle.message("file.not.exist.error", ioFile.getPath())); + } + File ioTarget = new File(convertToIOFile(parent), newName); + if (!sameName && ioTarget.exists()) { + throw new IOException(VfsBundle.message("target.already.exists.error", ioTarget.getPath())); + } if (!auxRename(file, newName)) { - final File target = new File(convertToIOFile(parent), newName); - if (!convertToIOFile(file).renameTo(target)) { - if (target.exists()) { - throw new IOException("Destination already exists: " + parent.getPath() + "/" + newName); - } else { - throw new IOException("Unable to rename " + file.getPath()); - } + if (!ioFile.renameTo(ioTarget)) { + throw new IOException(VfsBundle.message("rename.failed.error", ioFile.getPath(), newName)); } } + auxNotifyCompleted(new ThrowableConsumer() { @Override public void consume(LocalFileOperationsHandler handler) throws IOException { @@ -532,49 +607,62 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { @NotNull @Override - public VirtualFile copyFile(final Object requestor, - @NotNull final VirtualFile vFile, + public VirtualFile copyFile(Object requestor, + @NotNull final VirtualFile file, @NotNull final VirtualFile newParent, @NotNull final String copyName) throws IOException { - if (!PathUtil.isValidFileName(copyName)) { - throw new IOException("Invalid file name: " + copyName); + if (!VirtualFile.isValidName(copyName)) { + throw new IOException(VfsBundle.message("file.invalid.name.error", copyName)); } - FileAttributes attributes = getAttributes(vFile); - if (attributes == null || attributes.isSpecial()) { - throw new FileNotFoundException("Not a file: " + vFile); + if (!file.exists()) { + throw new IOException(VfsBundle.message("vfs.file.not.exist.error", file.getPath())); + } + if (!newParent.exists() || !newParent.isDirectory()) { + throw new IOException(VfsBundle.message("vfs.target.not.directory.error", newParent.getPath())); + } + if (newParent.findChild(copyName) != null) { + throw new IOException(VfsBundle.message("vfs.target.already.exists.error", newParent.getPath() + "/" + copyName)); } - File physicalFile = convertToIOFile(vFile); - File physicalCopy = auxCopy(vFile, newParent, copyName); + FileAttributes attributes = getAttributes(file); + if (attributes == null) { + throw new FileNotFoundException(VfsBundle.message("file.not.exist.error", file.getPath())); + } + if (attributes.isSpecial()) { + throw new FileNotFoundException("Not a file: " + file); + } + File ioParent = convertToIOFile(newParent); + if (!ioParent.isDirectory()) { + throw new IOException(VfsBundle.message("target.not.directory.error", ioParent.getPath())); + } + File ioTarget = new File(ioParent, copyName); + if (ioTarget.exists()) { + throw new IOException(VfsBundle.message("target.already.exists.error", ioTarget.getPath())); + } - try { - if (physicalCopy == null) { - File newPhysicalParent = convertToIOFile(newParent); - physicalCopy = new File(newPhysicalParent, copyName); - - try { - if (attributes.isDirectory()) { - FileUtil.copyDir(physicalFile, physicalCopy); - } - else { - FileUtil.copy(physicalFile, physicalCopy); - } + if (!auxCopy(file, newParent, copyName)) { + try { + File ioFile = convertToIOFile(file); + if (attributes.isDirectory()) { + FileUtil.copyDir(ioFile, ioTarget); } - catch (IOException e) { - FileUtil.delete(physicalCopy); - throw e; + else { + FileUtil.copy(ioFile, ioTarget); } } + catch (IOException e) { + FileUtil.delete(ioTarget); + throw e; + } } - finally { - auxNotifyCompleted(new ThrowableConsumer() { - @Override - public void consume(LocalFileOperationsHandler handler) throws IOException { - handler.copy(vFile, newParent, copyName); - } - }); - } + + auxNotifyCompleted(new ThrowableConsumer() { + @Override + public void consume(LocalFileOperationsHandler handler) throws IOException { + handler.copy(file, newParent, copyName); + } + }); return new FakeVirtualFile(newParent, copyName); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index 6a326f1a70d4..de1790b6dee2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -225,7 +225,7 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom @Override public final Rectangle getScreenBounds() { - return ScreenUtil.getAllScreensShape().getBounds(); + return ScreenUtil.getAllScreensRectangle(); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java index 68482d0d432a..addbc4f46f41 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java @@ -109,9 +109,11 @@ public class NewRecentProjectPanel extends RecentProjectPanel { closeButtonCell.gridx = 1; closeButtonCell.gridy = 0; + closeButtonCell.anchor = GridBagConstraints.FIRST_LINE_END; + closeButtonCell.insets = new Insets(7, 7, 7, 7); closeButtonCell.gridheight = 2; - closeButtonCell.anchor = GridBagConstraints.WEST; + //closeButtonCell.anchor = GridBagConstraints.WEST; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java index f9a855ae5116..fd15deb7b588 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java @@ -47,7 +47,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import java.awt.*; import java.awt.event.*; @@ -58,19 +57,38 @@ public class RecentProjectPanel extends JPanel { protected final UniqueNameBuilder myPathShortener; protected AnAction removeRecentProjectAction; private int myHoverIndex = -1; + private static final int closeButtonInset = 7; + private Icon currentIcon = AllIcons.Welcome.RemoveRecentProject; private final JPanel myCloseButtonForEditor = new JPanel() { { - setPreferredSize(new Dimension(AllIcons.General.BalloonClose.getIconWidth(), AllIcons.General.BalloonClose.getIconHeight())); + setPreferredSize(new Dimension(currentIcon.getIconWidth(), currentIcon.getIconHeight())); setOpaque(true); } @Override protected void paintComponent(Graphics g) { - AllIcons.General.BalloonClose.paintIcon(this, g, 0, 0); + currentIcon.paintIcon(this, g, 0, 0); } }; + + private boolean rectInListCoordinatesContains(Rectangle listCellBounds, Point p) { + + int realCloseButtonInset = (UIUtil.isRetina(myList.getGraphicsConfiguration().getDevice())) ? + closeButtonInset * 2 : closeButtonInset; + + Rectangle closeButtonRect = new Rectangle(myCloseButtonForEditor.getX() - realCloseButtonInset, + myCloseButtonForEditor.getY() - realCloseButtonInset, + myCloseButtonForEditor.getWidth() + realCloseButtonInset * 2, + myCloseButtonForEditor.getHeight() + realCloseButtonInset * 2); + + Rectangle rectInListCoordinates = new Rectangle(new Point(closeButtonRect.x + listCellBounds.x, + closeButtonRect.y + listCellBounds.y), + closeButtonRect.getSize()); + return rectInListCoordinates.contains(p); + } + public RecentProjectPanel(WelcomeScreen screen) { super(new BorderLayout()); @@ -93,12 +111,7 @@ public class RecentProjectPanel extends JPanel { Rectangle cellBounds = myList.getCellBounds(selectedIndex, selectedIndex); if (cellBounds.contains(event.getPoint())) { Object selection = myList.getSelectedValue(); - - Rectangle closeButtonRect = myCloseButtonForEditor.getBounds(); - - Rectangle rectInListCoordinates = new Rectangle(new Point(closeButtonRect.x + cellBounds.x, closeButtonRect.y + cellBounds.y), closeButtonRect.getSize()); - - if (Registry.is("removable.welcome.screen.projects") && rectInListCoordinates.contains(event.getPoint())) { + if (Registry.is("removable.welcome.screen.projects") && rectInListCoordinatesContains(cellBounds, event.getPoint())) { removeRecentProjectAction.actionPerformed(null); } else if (selection != null) { ((AnAction)selection).actionPerformed( @@ -203,11 +216,16 @@ public class RecentProjectPanel extends JPanel { int index = myList.locationToIndex(point); myList.setSelectedIndex(index); - final Rectangle bounds = myList.getCellBounds(index, index); - if (bounds != null && bounds.contains(point)) { + final Rectangle cellBounds = myList.getCellBounds(index, index); + if (cellBounds != null && cellBounds.contains(point)) { myList.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + if (rectInListCoordinatesContains(cellBounds, point)) { + currentIcon = AllIcons.Welcome.RemoveRecentProjectHover; + } else { + currentIcon = AllIcons.Welcome.RemoveRecentProject; + } myHoverIndex = index; - myList.repaint(bounds); + myList.repaint(cellBounds); } else { myList.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); @@ -223,6 +241,7 @@ public class RecentProjectPanel extends JPanel { @Override public void mouseExited(MouseEvent e) { myHoverIndex = -1; + currentIcon = AllIcons.Welcome.RemoveRecentProject; myList.repaint(); } }; @@ -261,7 +280,7 @@ public class RecentProjectPanel extends JPanel { private static class MyList extends JBList { private final Dimension mySize; - private MyList(Dimension size, @NotNull Object... listData) { + private MyList(Dimension size, @NotNull Object ... listData) { super(listData); mySize = size; setEmptyText(" No Project Open Yet "); diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java b/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java index cb66ab0bcd6c..6a1a9837beef 100644 --- a/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java +++ b/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java @@ -36,7 +36,7 @@ public abstract class ProjectTemplatesFactory { public abstract String[] getGroups(); @NotNull - public abstract ProjectTemplate[] createTemplates(String group, WizardContext context); + public abstract ProjectTemplate[] createTemplates(@NotNull String group, WizardContext context); public Icon getGroupIcon(String group) { return null; diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index b0bda1b30d73..10af58c551c6 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -276,9 +276,11 @@ public abstract class AbstractExpandableItemsHandler visMaxY) return null; + + int cellMaxX = cellBounds.x + cellBounds.width; + int visMaxX = visibleRect.x + visibleRect.width; + + Point location = new Point(visMaxX, cellBounds.y); + SwingUtilities.convertPointToScreen(location, myComponent); + + Rectangle screen = !Registry.is("ide.expansion.hints.on.all.screens") + ? ScreenUtil.getScreenRectangle(location) + : ScreenUtil.getAllScreensRectangle(); + + int borderWidth = isPaintBorder() ? 1 : 0; + int width = Math.min(screen.width + screen.x - location.x - borderWidth, cellMaxX - visMaxX); int height = cellBounds.height; if (width <= 0 || height <= 0) return null; - if (cellBounds.y < visibleRect.y) return null; - if (cellBounds.y + cellBounds.height > visibleRect.y + visibleRect.height) return null; Dimension size = getImageSize(width, height); myImage = UIUtil.createImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); @@ -399,16 +394,15 @@ public abstract class AbstractExpandableItemsHandler 0) { + border = new CustomLineBorder(getBorderColor(), borderWidth, 0, borderWidth, borderWidth); + location.y -= borderWidth; + size.width += borderWidth; + size.height += borderWidth + borderWidth; } g.dispose(); diff --git a/platform/platform-impl/src/com/intellij/util/io/HttpRequestsImpl.java b/platform/platform-impl/src/com/intellij/util/io/HttpRequestsImpl.java deleted file mode 100644 index fba7ccc1dbc6..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/HttpRequestsImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.util.io; - -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ex.ApplicationInfoEx; -import org.jetbrains.annotations.NotNull; - -class HttpRequestsImpl extends HttpRequests { - @Override - protected RequestBuilder createRequestBuilder(@NotNull String url) { - return new RequestBuilder(url) { - @NotNull - @Override - public RequestBuilder userAgent() { - Application app = ApplicationManager.getApplication(); - if (app != null && !app.isDisposed()) { - return userAgent(ApplicationInfoEx.getInstanceEx().getFullApplicationName()); - } - else { - return userAgent("IntelliJ IDEA (?)"); - } - } - }; - } -} diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java index 89cd47453b92..d27e89ce2019 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java +++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java @@ -483,10 +483,12 @@ public abstract class JBListTable { * @return whether this row animation is complete */ public boolean doAnimationStep(long currentTime) { + if (myRow >= myTable.getRowCount()) return true; + int currentRowHeight = myTable.getRowHeight(myRow); int resizeAbs = (int) (RESIZE_AMOUNT_PER_STEP * ((currentTime - myLastUpdateTime) / (double)ANIMATION_STEP_MILLIS)); int leftToAnimate = myTargetHeight - currentRowHeight; - int newHeight = Math.abs(leftToAnimate) <= Math.abs(resizeAbs) ? myTargetHeight : + int newHeight = Math.abs(leftToAnimate) <= resizeAbs ? myTargetHeight : currentRowHeight + (leftToAnimate < 0 ? -resizeAbs : resizeAbs); myTable.setRowHeight(myRow, newHeight); myLastUpdateTime = currentTime; diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 725bd00182a7..29121a5e3a0c 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -344,7 +344,6 @@ checkbox.show.whitespaces=Show whitespaces checkbox.show.leading.whitespaces=Leading checkbox.show.inner.whitespaces=Inner checkbox.show.trailing.whitespaces=Trailing -checkbox.show.all.softwraps=Show all soft wraps checkbox.show.method.separators=Show method separators checkbox.show.small.icons.in.gutter=Show icons preview in gutter for small icons (Java) checkbox.show.line.numbers=Show line numbers @@ -387,10 +386,13 @@ label.when.closing.active.editor=When closing active editor: radio.close.less.frequently.used.files=Close less frequently used files radio.close.non.modified.files.first=Close non-modified files first label.when.number.of.opened.editors.exceeds.tab.limit=When number of opened editors exceeds tab limit: -group.virtual.space=Virtual Space +group.soft.wraps=Soft Wraps checkbox.use.soft.wraps.at.editor=Use soft wraps in editor checkbox.use.soft.wraps.at.console=Use soft wraps in console -checkbox.use.custom.soft.wraps.indent=Use custom soft wraps indent +checkbox.use.custom.soft.wraps.indent=Use original line's indent for wrapped parts. Additional shift: +checkbox.show.softwraps.only.for.caret.line=Show soft wraps for current line only +checkbox.show.softwraps.only.for.caret.line.action.text=Soft Wraps: Show for current line only +group.virtual.space=Virtual Space checkbox.allow.placement.of.caret.after.end.of.line=Allow placement of caret after end of line checkbox.allow.placement.of.caret.inside.tabs=Allow placement of caret inside tabs checkbox.show.virtual.space.at.file.bottom=Show virtual space at file bottom diff --git a/platform/platform-resources-en/src/messages/CodeEditorBundle.properties b/platform/platform-resources-en/src/messages/CodeEditorBundle.properties index 82a29b7c5435..a1c47c6de185 100644 --- a/platform/platform-resources-en/src/messages/CodeEditorBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeEditorBundle.properties @@ -52,11 +52,12 @@ print.header.alignment.combobox=Alignment print.apply.button=A&pply print.progress=Printing... print.header.default.line.1=File - $FILE$ -print.header.default.line.2=Page $PAGE$ +print.header.default.line.2=Page $PAGE$ of $TOTALPAGES$ print.header.placement.header=Header print.header.placement.footer=Footer print.header.alignment.left=Left print.header.alignment.center=Center print.header.alignment.right=Right -print.file.page.progress=Printing {0}. Page {1}... +print.file.calculating.number.of.pages.progress=Calculating number of pages... +print.file.page.progress=Printing {0}. Page {1} of {2} file.not.found=File not found: {0} diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index c3c03bdffb8f..72992af11a4f 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -285,6 +285,7 @@ javadoc.documentation.not.found.message=The documentation for this element is no javadoc.documentation.not.found.title=No Documentation javadoc.fetching.progress=Fetching Documentation... no.documentation.found=No documentation found. +javadoc.constructor.candidates=Candidates for new {0}() are:
{1} javadoc.candidates=Candidates for method call {0} are:

{1} javadoc.candidates.not.found=No candidates found for method call {0}. declaration.navigation.title=Choose Declaration diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 2cc34d3f5082..8f4fa6e21aaf 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -131,6 +131,7 @@ title.select.template=Select Template label.name=Name: label.extension=Extension: title.file.templates=File and Code Templates +title.edit.file.template=Edit File Template checkbox.reformat.according.to.style=Reformat according to style label.description=Description item.file.templates=File templates diff --git a/platform/platform-resources-en/src/messages/VfsBundle.properties b/platform/platform-resources-en/src/messages/VfsBundle.properties index f9c5c0c0a581..293cc3026d97 100644 --- a/platform/platform-resources-en/src/messages/VfsBundle.properties +++ b/platform/platform-resources-en/src/messages/VfsBundle.properties @@ -15,15 +15,28 @@ cannot.create.local.file=Cannot create local file: {0} download.progress.connecting=Connecting to ''{0}''... download.progress.downloading=Downloading ''{0}''... -file.invalid.name.error=Invalid file name: \"{0}\" -directory.invalid.name.error=Invalid directory name: \"{0}\" +vfs.file.not.exist.error=''{0}'' does not exist in VFS +vfs.target.already.exists.error=''{0}'' already exists in VFS +vfs.target.not.directory.error=''{0}'' is not a directory in VFS +file.not.exist.error=''{0}'' does not exist +target.already.exists.error=''{0}'' already exists +target.not.directory.error=''{0}'' is not a directory +file.invalid.name.error=Invalid file name: ''{0}'' +directory.invalid.name.error=Invalid directory name: ''{0}'' + +rename.failed.error=Cannot rename ''{0}'' to ''{1}'' +move.failed.error=Cannot move ''{0}'' to ''{1}'' +delete.failed.error=Cannot delete ''{0}'' +new.file.failed.error=Cannot create file ''{0}'' +new.directory.failed.error=Cannot create directory ''{0}'' + directory.create.wrong.parent.error=Not a directory. Cannot create new directory in. file.create.wrong.parent.error=Not a directory. Cannot create new file in. file.already.exists.error=Cannot create file ''{0}''. File already exists. dir.already.exists.error=Cannot create directory ''{0}''. Directory already exists. invalid.directory.create.files=Invalid directory. Cannot create files. -file.delete.error=Cannot delete file {0}. -file.move.error=Can not move file to {0} -file.copy.error=Can not copy file to {0} +file.move.error=Cannot move file to {0} +file.copy.error=Cannot copy file to {0} file.copy.target.must.be.directory=Cannot copy, target must be directory. -cannot.rename.root.directory=Cannot rename root directory. \ No newline at end of file +cannot.rename.root.directory=Cannot rename root directory ''{0}'' +cannot.delete.root.directory=Cannot delete root directory ''{0}'' diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties index 53c4fc55aa1f..928d26855bf0 100644 --- a/platform/platform-resources-en/src/messages/XmlBundle.properties +++ b/platform/platform-resources-en/src/messages/XmlBundle.properties @@ -71,10 +71,13 @@ html.inspections.non.existent.internet.resource.name=Non-existent web resource html.inspections.unknown.tag=Unknown HTML tag html.inspections.unknown.attribute=Unknown HTML tag attribute +html.inspections.unknown.boolean.attribute=Unknown HTML boolean tag attribute html.inspections.unknown.tag.checkbox.title=Custom HTML tags: html.inspections.unknown.tag.title=Edit custom tags html.inspections.unknown.tag.attribute.checkbox.title=Custom HTML tag attributes: +html.inspections.unknown.tag.boolean.attribute.checkbox.title=Custom HTML boolean tag attributes: html.inspections.unknown.tag.attribute.title=Edit custom attributes +html.inspections.unknown.tag.boolean.attribute.title=Edit custom boolean attributes xml.schema.create.complex.type.intention.name=Create Complex Type {0} xml.schema.create.attribute.intention.name=Create Attribute {0} xml.schema.create.element.intention.name=Create Element {0} @@ -130,6 +133,7 @@ no.ignored.resources=No ignored resources custom.html.tag=Custom Html Tag add.custom.html.tag=Add {0} to custom html tags add.custom.html.attribute=Add {0} to custom html attributes +add.custom.html.boolean.attribute=Add {0} to custom html boolean attributes add.optional.html.attribute=Add {0} to not required html attributes fix.html.family=Fix Html @@ -200,7 +204,7 @@ xmlbeans.particle.valid.tooltip=Enable particle valid (restriction) rule xmlbeans.unique.particle.tooltip=Enable unique particle rule xmlbeans.designtype.tooltip=XMLSchema design type xmlbeans.simplecontenttype.tooltip=Simple content types detection (leaf text) -xmlbeans.enumerations.tooltip=Detection enumeration from following count +xmlbeans.enumerations.tooltip=Detection enumeration from following count webservice.status.tooltip=Status of current settings, input errors, etc xmlbeans.instance2schema.result.schema.name=Result schema file name browse.button.tooltip=Browse for local file diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 609aa5a38167..c40d2ed178f0 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -265,8 +265,6 @@ - - @@ -335,8 +333,6 @@ - - diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index cf0e8e7b97c8..3ada69d17e89 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -421,6 +421,9 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java b/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java index 8fe3951dcd11..095cb524d801 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/GeneralCommandLineTest.java @@ -17,6 +17,7 @@ package com.intellij.execution; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -239,6 +240,13 @@ public class GeneralCommandLineTest { checkEnvPassing(commandLine, testEnv, false); } + @Test + public void emptyEnvironmentPassing() throws Exception { + Pair nonEmpty = Pair.create("a", "b"); + Map inputEnv = newHashMap(Pair.create("", "c"), nonEmpty); + GeneralCommandLine commandLine = makeJavaCommand(EnvPassingTest.class, null); + checkEnvPassing(commandLine, inputEnv, SystemInfo.isWindows ? newHashMap(nonEmpty) : inputEnv, false); + } private static String execAndGetOutput(GeneralCommandLine commandLine, @Nullable String encoding) throws Exception { Process process = commandLine.createProcess(); @@ -284,6 +292,13 @@ public class GeneralCommandLineTest { } private static void checkEnvPassing(GeneralCommandLine commandLine, Map testEnv, boolean passParentEnv) throws Exception { + checkEnvPassing(commandLine, testEnv, testEnv, passParentEnv); + } + + private static void checkEnvPassing(GeneralCommandLine commandLine, + Map testEnv, + Map expectedOutputEnv, + boolean passParentEnv) throws Exception { commandLine.getEnvironment().putAll(testEnv); commandLine.setPassParentEnvironment(passParentEnv); String output = execAndGetOutput(commandLine, null); @@ -291,7 +306,7 @@ public class GeneralCommandLineTest { Set lines = new HashSet(Arrays.asList(StringUtil.convertLineSeparators(output).split("\n"))); lines.remove("====="); - for (Map.Entry entry : testEnv.entrySet()) { + for (Map.Entry entry : expectedOutputEnv.entrySet()) { String str = EnvPassingTest.format(entry); assertTrue("\"" + str + "\" should be in " + lines, lines.contains(str)); diff --git a/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java b/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java index 3eba2bd1493e..ecce6a5ad2a7 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java @@ -117,6 +117,24 @@ public class LightFileTemplatesTest extends LightPlatformTestCase { } } + public void testRemoveTemplate() throws Exception { + FileTemplate[] before = myTemplateManager.getAllTemplates(); + try { + FileTemplate template = myTemplateManager.getTemplate(TEST_TEMPLATE_TXT); + myTemplateManager.removeTemplate(template); + assertNull(myTemplateManager.getTemplate(TEST_TEMPLATE_TXT)); + myTemplateManager.setCurrentScheme(myTemplateManager.getProjectScheme()); + assertNull(myTemplateManager.getTemplate(TEST_TEMPLATE_TXT)); + myTemplateManager.setCurrentScheme(FileTemplatesScheme.DEFAULT); + assertNull(myTemplateManager.getTemplate(TEST_TEMPLATE_TXT)); + } + finally { + myTemplateManager.setTemplates(FileTemplateManager.DEFAULT_TEMPLATES_CATEGORY, Arrays.asList(before)); + myTemplateManager.setCurrentScheme(myTemplateManager.getProjectScheme()); + myTemplateManager.setTemplates(FileTemplateManager.DEFAULT_TEMPLATES_CATEGORY, Arrays.asList(before)); + } + } + private FileTemplateManagerImpl myTemplateManager; @Override diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ApplicationStoreTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ApplicationStoreTest.java index bb17ec43dd8b..58c06e218791 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ApplicationStoreTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ApplicationStoreTest.java @@ -214,7 +214,7 @@ public class ApplicationStoreTest extends LightPlatformLangTestCase { @Nullable @Override - protected StateStorage getDefaultsStorage() { + protected PathMacroManager getPathMacroManagerForDefaults() { return null; } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ProjectStoreBaseTestCase.java b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ProjectStoreBaseTestCase.java index 5d566ec77023..253700c492a5 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ProjectStoreBaseTestCase.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/ProjectStoreBaseTestCase.java @@ -18,14 +18,22 @@ package com.intellij.openapi.components.impl; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.util.JDOMBuilder; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.testFramework.PlatformLangTestCase; +import java.io.File; import java.io.UnsupportedEncodingException; public abstract class ProjectStoreBaseTestCase extends PlatformLangTestCase { + @Override + protected Project doCreateProject(File projectFile) throws Exception { + return ProjectManagerEx.getInstanceEx().loadProject(projectFile.getAbsolutePath()); + } + protected byte[] getIprFileContent() throws UnsupportedEncodingException { final String iprContent = JDOMUtil.writeDocument( JDOMBuilder.document(JDOMBuilder.tag("project", diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java index 30e7860638b6..f6dff65607ba 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/FoldingTest.java @@ -22,6 +22,7 @@ import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.TestFileType; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertTrue; /** * @author max @@ -195,4 +196,24 @@ public class FoldingTest extends AbstractEditorTest { assertTrue(myModel.isOffsetCollapsed(5)); } + + public void testIdenticalRegionsAreRemoved() { + addFoldRegion(0, 5, "..."); + addFoldRegion(0, 4, "..."); + assertNumberOfValidFoldRegions(2); + + myEditor.getDocument().deleteString(4, 5); + + assertNumberOfValidFoldRegions(1); + } + + private void assertNumberOfValidFoldRegions(int expectedValue) { + int actualValue = 0; + for (FoldRegion region : myModel.getAllFoldRegions()) { + if (region.isValid()) { + actualValue++; + } + } + assertEquals(expectedValue, actualValue); + } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index 6f1e8c0657c3..5fb8396715ed 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -1106,6 +1106,17 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT verifySoftWrapPositions(); } + public void testFoldRegionPreventsLaterWrapping() throws Exception { + initText("unbreakableText.txt"); + configureSoftWraps(10); + verifySoftWrapPositions(15); + + addCollapsedFoldRegion(12, 13, "."); + + verifySoftWrapPositions(12); + assertEquals(1, myEditor.offsetToVisualPosition(19).line); + } + private void init(final int visibleWidthInColumns, @NotNull String fileText) throws IOException { init(visibleWidthInColumns, 7, fileText); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java index 82bda836bf89..c75f101e5357 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java @@ -17,6 +17,8 @@ package com.intellij.openapi.vfs.local; import com.intellij.ide.GeneralSettings; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtil; @@ -452,7 +454,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { assertEquals(newName, sourceFile.getName()); topDir.getChildren(); - newName = newName.toLowerCase(); + newName = newName.toLowerCase(Locale.ENGLISH); FileUtil.rename(file, intermediate); FileUtil.rename(intermediate, new File(top, newName)); topDir.refresh(false, true); @@ -582,4 +584,43 @@ public class LocalFileSystemTest extends PlatformLangTestCase { RefreshWorker.setCancellingCondition(null); } } + + public void testInvalidFileName() { + new WriteAction() { + @Override + protected void run(@NotNull Result result) throws Throwable { + VirtualFile tempDir = myFS.refreshAndFindFileByIoFile(createTempDirectory()); + assertNotNull(tempDir); + try { + tempDir.createChildData(this, "a/b"); + fail("invalid file name should have been rejected"); + } + catch (IOException e) { + assertEquals(VfsBundle.message("file.invalid.name.error", "a/b"), e.getMessage()); + } + } + }.execute(); + } + + public void testDuplicateViaRename() { + new WriteAction() { + @Override + protected void run(@NotNull Result result) throws Throwable { + VirtualFile tempDir = myFS.refreshAndFindFileByIoFile(createTempDirectory()); + assertNotNull(tempDir); + + VirtualFile file1 = tempDir.createChildData(this, "a.txt"); + FileUtil.delete(VfsUtilCore.virtualToIoFile(file1)); + + VirtualFile file2 = tempDir.createChildData(this, "b.txt"); + try { + file2.rename(this, "a.txt"); + fail("duplicate file name should have been rejected"); + } + catch (IOException e) { + assertEquals(VfsBundle.message("vfs.target.already.exists.error", file1.getPath()), e.getMessage()); + } + } + }.execute(); + } } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index 36ff59196ea4..24b3926c98aa 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -21,6 +21,7 @@ import com.intellij.execution.testframework.sm.SMStacktraceParser; import com.intellij.execution.testframework.sm.TestsLocationProviderUtil; import com.intellij.execution.testframework.sm.runner.states.*; import com.intellij.execution.testframework.sm.runner.ui.TestsPresentationUtil; +import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.ide.util.EditSourceUtil; import com.intellij.openapi.application.ApplicationManager; @@ -550,15 +551,15 @@ public class SMTestProxy extends AbstractTestProxy { @Override @Nullable - public AssertEqualsDiffViewerProvider getDiffViewerProvider() { - if (myState instanceof AssertEqualsDiffViewerProvider) { - return (AssertEqualsDiffViewerProvider)myState; + public DiffHyperlink getDiffViewerProvider() { + if (myState instanceof TestComparisionFailedState) { + return ((TestComparisionFailedState)myState).getHyperlink(); } if (myChildren != null) { for (SMTestProxy child : myChildren) { if (!child.isDefect()) continue; - final AssertEqualsDiffViewerProvider provider = child.getDiffViewerProvider(); + final DiffHyperlink provider = child.getDiffViewerProvider(); if (provider != null) { return provider; } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java index 461001d3b111..dc5fef7166d0 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java @@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable; /** * @author Roman.Chernyatchik */ -public class TestComparisionFailedState extends TestFailedState implements AbstractTestProxy.AssertEqualsMultiDiffViewProvider { +public class TestComparisionFailedState extends TestFailedState { private final String myErrorMsgPresentation; private final String myStacktracePresentation; private DiffHyperlink myHyperlink; @@ -64,27 +64,8 @@ public class TestComparisionFailedState extends TestFailedState implements Abstr printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT); } - public void openDiff(final Project project) { - myHyperlink.openDiff(project); - } - - @Override - public String getExpected() { - return myHyperlink.getLeft(); - } - - @Override - public String getActual() { - return myHyperlink.getRight(); - } - - @Override - public void openMultiDiff(Project project, AbstractTestProxy.AssertEqualsDiffChain chain) { - myHyperlink.openMultiDiff(project, chain); - } - - @Override - public String getFilePath() { - return myHyperlink.getFilePath(); + @Nullable + public DiffHyperlink getHyperlink() { + return myHyperlink; } } diff --git a/platform/structuralsearch/source/messages/SSRBundle.properties b/platform/structuralsearch/source/messages/SSRBundle.properties index 03e22b45699a..9cf09ff14739 100644 --- a/platform/structuralsearch/source/messages/SSRBundle.properties +++ b/platform/structuralsearch/source/messages/SSRBundle.properties @@ -101,6 +101,7 @@ predefined.configuration.class.implements.two.interfaces=class implementing two predefined.configuration.bean.info.classes=Bean info classes predefined.configuration.all.expressions.of.some.type=all expressions of some type predefined.configuration.variables.of.generic.types=variables of generic types +predefined.configuration.diamond.operators=diamond operators predefined.configuration.comments=comments predefined.configuration.fields_variables.with.given.name.pattern.updated=fields/variables with given name pattern updated predefined.configuration.trys=try's @@ -145,6 +146,7 @@ predefined.configuration.packagelocal.fields.of.the.class=package local fields o predefined.configuration.classes=classes predefined.configuration.new.expressions=new expressions predefined.configuration.lambdas=lambdas +predefined.configuration.method.references=method references # edit variable constraint dialog options invalid.regular.expression=Invalid regular expression diff --git a/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java b/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java index 400744bcc9e0..b7e33f6d6ef2 100644 --- a/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java +++ b/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java @@ -15,7 +15,6 @@ */ package com.intellij.projectView; -import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.ide.projectView.impl.AbstractProjectTreeStructure; import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane; import com.intellij.openapi.Disposable; @@ -97,8 +96,4 @@ public class TestProjectTreeStructure extends AbstractProjectTreeStructure imple @Override public void dispose() { } - - public String getProjectFileRepresentation() { - return " " + myProject.getName() + ProjectFileType.DOT_DEFAULT_EXTENSION + "\n"; - } } diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java index b6dc8b458d06..40d8994e1cb1 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java @@ -68,7 +68,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public abstract class LightPlatformCodeInsightTestCase extends LightPlatformLangTestCase { +public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTestCase { private static final Logger LOG = Logger.getInstance("#com.intellij.testFramework.LightCodeInsightTestCase"); protected static Editor myEditor; diff --git a/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java index 279e640d4a2d..ccc7c0a46787 100644 --- a/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/VfsTestUtil.java @@ -67,16 +67,18 @@ public class VfsTestUtil { } parent = child; } - final VirtualFile file; + + VirtualFile file; parent.getChildren();//need this to ensure that fileCreated event is fired if (dir) { file = parent.createChildDirectory(VfsTestUtil.class, PathUtil.getFileName(relativePath)); } else { - file = parent.createChildData(VfsTestUtil.class, PathUtil.getFileName(relativePath)); - if (!text.isEmpty()) { - VfsUtil.saveText(file, text); + file = parent.findFileByRelativePath(relativePath); + if (file == null) { + file = parent.createChildData(VfsTestUtil.class, PathUtil.getFileName(relativePath)); } + VfsUtil.saveText(file, text); } return file; } diff --git a/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockUpdateParameterInfoContext.java b/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockUpdateParameterInfoContext.java index 25679f485eb6..a1bfed07dc5b 100644 --- a/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockUpdateParameterInfoContext.java +++ b/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockUpdateParameterInfoContext.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author gregsh @@ -32,10 +33,18 @@ public class MockUpdateParameterInfoContext implements UpdateParameterInfoContex private PsiElement myParameterOwner; private Object myHighlightedParameter; private int myCurrentParameter; + private final Object[] myItems; + private final boolean[] myCompEnabled; public MockUpdateParameterInfoContext(@NotNull Editor editor, @NotNull PsiFile file) { + this(editor, file, null); + } + + public MockUpdateParameterInfoContext(@NotNull Editor editor, @NotNull PsiFile file, @Nullable Object[] items) { myEditor = editor; myFile = file; + myItems = items == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : items; + myCompEnabled = items == null ? null : new boolean[items.length]; } public void removeHint() {} @@ -58,16 +67,22 @@ public class MockUpdateParameterInfoContext implements UpdateParameterInfoContex return myCurrentParameter; } - public boolean isUIComponentEnabled(int index) { return false; } + public boolean isUIComponentEnabled(int index) { + return myCompEnabled != null && myCompEnabled[index]; + } - public void setUIComponentEnabled(int index, boolean b) {} + public void setUIComponentEnabled(int index, boolean b) { + if (myCompEnabled != null) { + myCompEnabled[index] = b; + } + } public int getParameterListStart() { return myEditor.getCaretModel().getOffset(); } public Object[] getObjectsToView() { - return ArrayUtil.EMPTY_OBJECT_ARRAY; + return myItems; } public Project getProject() { diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java index bc20186244dd..6643acfd3803 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java @@ -132,7 +132,7 @@ public abstract class AbstractVcsTestCase { } public VirtualFile createDirInCommand(final VirtualFile parent, final String name) { - return VcsTestUtil.createDir(myProject, parent, name); + return VcsTestUtil.findOrCreateDir(myProject, parent, name); } protected void clearDirInCommand(final VirtualFile dir, final Processor filter) { diff --git a/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java b/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java index 7b84c66ae2ac..d30295951ba8 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java @@ -21,6 +21,7 @@ package com.intellij.execution.testframework; import com.intellij.execution.Location; +import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -134,25 +135,14 @@ public abstract class AbstractTestProxy extends CompositePrintable { } @Nullable - public AssertEqualsDiffViewerProvider getDiffViewerProvider() { + public DiffHyperlink getDiffViewerProvider() { return null; } - public interface AssertEqualsDiffViewerProvider { - void openDiff(final Project project); - String getExpected(); - String getActual(); - } - public interface AssertEqualsDiffChain { - AssertEqualsMultiDiffViewProvider getPrevious(); - AssertEqualsMultiDiffViewProvider getCurrent(); - AssertEqualsMultiDiffViewProvider getNext(); - void setCurrent(AssertEqualsMultiDiffViewProvider provider); - } - - public interface AssertEqualsMultiDiffViewProvider extends AssertEqualsDiffViewerProvider { - void openMultiDiff(Project project, AssertEqualsDiffChain chain); - String getFilePath(); + DiffHyperlink getPrevious(); + DiffHyperlink getCurrent(); + DiffHyperlink getNext(); + void setCurrent(DiffHyperlink provider); } } diff --git a/platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java b/platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java index 36b9e2459ba3..a5615647ab6e 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java @@ -20,10 +20,13 @@ import com.intellij.execution.testframework.AbstractTestProxy; import com.intellij.execution.testframework.TestFrameworkRunningModel; import com.intellij.execution.testframework.TestTreeView; import com.intellij.execution.testframework.TestTreeViewAction; +import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; @@ -33,25 +36,23 @@ public class ViewAssertEqualsDiffAction extends AnAction implements TestTreeView @NonNls public static final String ACTION_ID = "openAssertEqualsDiff"; public void actionPerformed(final AnActionEvent e) { - if (!openDiff(e.getDataContext())) { + if (!openDiff(e.getDataContext(), null)) { final Component component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT); Messages.showInfoMessage(component, "Comparison error was not found", "No Comparison Data Found"); } } - public static boolean openDiff(DataContext context) { + public static boolean openDiff(DataContext context, @Nullable DiffHyperlink currentHyperlink) { final AbstractTestProxy testProxy = AbstractTestProxy.DATA_KEY.getData(context); if (testProxy != null) { - final AbstractTestProxy.AssertEqualsDiffViewerProvider diffViewerProvider = testProxy.getDiffViewerProvider(); + DiffHyperlink diffViewerProvider = testProxy.getDiffViewerProvider(); if (diffViewerProvider != null) { final Project project = CommonDataKeys.PROJECT.getData(context); - if (diffViewerProvider instanceof AbstractTestProxy.AssertEqualsMultiDiffViewProvider) { - final TestFrameworkRunningModel runningModel = TestTreeView.MODEL_DATA_KEY.getData(context); - final List providers = collectAvailableProviders(runningModel); - final MyAssertEqualsDiffChain diffChain = - providers.size() > 1 ? new MyAssertEqualsDiffChain(providers, (AbstractTestProxy.AssertEqualsMultiDiffViewProvider)diffViewerProvider) : null; - ((AbstractTestProxy.AssertEqualsMultiDiffViewProvider)diffViewerProvider).openMultiDiff(project, diffChain); - } else { + final List providers = collectAvailableProviders(TestTreeView.MODEL_DATA_KEY.getData(context)); + if (providers.size() > 1) { + new MyAssertEqualsDiffChain(providers, diffViewerProvider, currentHyperlink).openMultiDiff(project); + } + else { diffViewerProvider.openDiff(project); } return true; @@ -60,16 +61,16 @@ public class ViewAssertEqualsDiffAction extends AnAction implements TestTreeView return false; } - private static List collectAvailableProviders(TestFrameworkRunningModel model) { - final List providers = new ArrayList(); + private static List collectAvailableProviders(TestFrameworkRunningModel model) { + final List providers = new ArrayList(); if (model != null) { final AbstractTestProxy root = model.getRoot(); final List allTests = root.getAllTests(); for (AbstractTestProxy test : allTests) { if (test.isLeaf()) { - final AbstractTestProxy.AssertEqualsDiffViewerProvider provider = test.getDiffViewerProvider(); - if (provider instanceof AbstractTestProxy.AssertEqualsMultiDiffViewProvider) { - providers.add((AbstractTestProxy.AssertEqualsMultiDiffViewProvider)provider); + final DiffHyperlink provider = test.getDiffViewerProvider(); + if (provider != null) { + providers.add(provider); } } } @@ -108,35 +109,48 @@ public class ViewAssertEqualsDiffAction extends AnAction implements TestTreeView private static class MyAssertEqualsDiffChain implements AbstractTestProxy.AssertEqualsDiffChain { - private final List myProviders; - private AbstractTestProxy.AssertEqualsMultiDiffViewProvider myProvider; + private final List myProviders; + private DiffHyperlink myProvider; - public MyAssertEqualsDiffChain(List providers, - AbstractTestProxy.AssertEqualsMultiDiffViewProvider provider) { + public MyAssertEqualsDiffChain(List providers, + DiffHyperlink provider, + DiffHyperlink hyperlink) { myProviders = providers; + if (hyperlink != null) { + for (DiffHyperlink viewProvider : providers) { + if (Comparing.equal(hyperlink, viewProvider)) { + provider = viewProvider; + break; + } + } + } myProvider = provider; } @Override - public AbstractTestProxy.AssertEqualsMultiDiffViewProvider getPrevious() { + public DiffHyperlink getPrevious() { final int prevIdx = (myProviders.size() + myProviders.indexOf(myProvider) - 1) % myProviders.size(); return myProviders.get(prevIdx); } @Override - public AbstractTestProxy.AssertEqualsMultiDiffViewProvider getCurrent() { + public DiffHyperlink getCurrent() { return myProvider; } @Override - public AbstractTestProxy.AssertEqualsMultiDiffViewProvider getNext() { + public DiffHyperlink getNext() { final int nextIdx = (myProviders.indexOf(myProvider) + 1) % myProviders.size(); return myProviders.get(nextIdx); } @Override - public void setCurrent(AbstractTestProxy.AssertEqualsMultiDiffViewProvider provider) { + public void setCurrent(DiffHyperlink provider) { myProvider = provider; } + + public void openMultiDiff(Project project) { + myProvider.openMultiDiff(project, this); + } } } diff --git a/platform/testRunner/src/com/intellij/execution/testframework/stacktrace/DiffHyperlink.java b/platform/testRunner/src/com/intellij/execution/testframework/stacktrace/DiffHyperlink.java index 995a56eea597..4846c338c104 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/stacktrace/DiffHyperlink.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/stacktrace/DiffHyperlink.java @@ -29,6 +29,7 @@ import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.LocalFileSystem; @@ -42,6 +43,7 @@ import java.io.File; public class DiffHyperlink implements Printable { private static final String NEW_LINE = "\n"; + private static final Logger LOG = Logger.getInstance("#" + DiffHyperlink.class.getName()); protected final String myExpected; protected final String myActual; @@ -97,7 +99,7 @@ public class DiffHyperlink implements Printable { } @Override - protected AbstractTestProxy.AssertEqualsMultiDiffViewProvider getNextId() { + protected DiffHyperlink getNextId() { return chain.getPrevious(); } }); @@ -107,7 +109,7 @@ public class DiffHyperlink implements Printable { } @Override - protected AbstractTestProxy.AssertEqualsMultiDiffViewProvider getNextId() { + protected DiffHyperlink getNextId() { return chain.getNext(); } }); @@ -135,11 +137,12 @@ public class DiffHyperlink implements Printable { @Override public void actionPerformed(@NotNull AnActionEvent e) { final DiffViewer viewer = e.getData(PlatformDataKeys.DIFF_VIEWER); + LOG.assertTrue(viewer != null); final Project project = e.getData(CommonDataKeys.PROJECT); - final AbstractTestProxy.AssertEqualsMultiDiffViewProvider nextProvider = getNextId(); + final DiffHyperlink nextProvider = getNextId(); myChain.setCurrent(nextProvider); - final SimpleDiffRequest nextRequest = - createRequest(project, myChain, nextProvider.getFilePath(), nextProvider.getExpected(), nextProvider.getActual()); + final SimpleDiffRequest nextRequest = createRequest(project, myChain, + nextProvider.getFilePath(), nextProvider.getLeft(), nextProvider.getRight()); viewer.setDiffRequest(nextRequest); } @@ -150,7 +153,7 @@ public class DiffHyperlink implements Printable { e.getPresentation().setEnabled(project != null && viewer != null); } - protected abstract AbstractTestProxy.AssertEqualsMultiDiffViewProvider getNextId(); + protected abstract DiffHyperlink getNextId(); } protected String getTitle() { @@ -186,9 +189,31 @@ public class DiffHyperlink implements Printable { return string.indexOf('\n') != -1 || string.indexOf('\r') != -1; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DiffHyperlink)) return false; + + DiffHyperlink hyperlink = (DiffHyperlink)o; + + if (myActual != null ? !myActual.equals(hyperlink.myActual) : hyperlink.myActual != null) return false; + if (myExpected != null ? !myExpected.equals(hyperlink.myExpected) : hyperlink.myExpected != null) return false; + if (myFilePath != null ? !myFilePath.equals(hyperlink.myFilePath) : hyperlink.myFilePath != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myExpected != null ? myExpected.hashCode() : 0; + result = 31 * result + (myActual != null ? myActual.hashCode() : 0); + result = 31 * result + (myFilePath != null ? myFilePath.hashCode() : 0); + return result; + } + public class DiffHyperlinkInfo implements HyperlinkInfo { public void navigate(final Project project) { - if (ViewAssertEqualsDiffAction.openDiff(DataManager.getInstance().getDataContext())) { + if (ViewAssertEqualsDiffAction.openDiff(DataManager.getInstance().getDataContext(), DiffHyperlink.this)) { return; } openDiff(project); diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index c27a3f1b19ea..9f8a8badc36a 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -121,6 +121,7 @@ ide.tooltip.autoDismissDeadZone=300 ide.balloon.shadowEnabled=true ide.balloon.shadow.size=15 ide.expansion.hints.enabled=true +ide.expansion.hints.on.all.screens=false ide.register.bundled.fonts=true ide.register.bundled.fonts.description=Disables automatic registration of bundled fonts: SourceCodePro, Inconsolata @@ -470,6 +471,7 @@ spy.js.realtime.evaluation=false spy.js.realtime.evaluation.description=Enables spy-js autocomplete and realtime evaluation new.css.schema.enabled=true +html.prefer.short.notation.of.boolean.attributes=true editor.disable.rtl=false editor.disable.rtl.description=Disables RTL support in editor (which is broken now anyway) @@ -514,7 +516,7 @@ check.power.supply.for.mbp.description=Check for discrete video card and power s force.subpixel.hinting=false force.subpixel.hinting.description=Force using sub-pixel antialiasing -lcd.contrast.value=140 +lcd.contrast.value=100 lcd.contrast.value.description=Set LCD text contrast value from 100 to 250 removable.welcome.screen.projects=false diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index 2e3233570e37..abb675c2c6c2 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -1185,6 +1185,9 @@ public class AllIcons { public static final Icon OpenProject = IconLoader.getIcon("/welcome/openProject.png"); // 16x16 public static final Icon Register = IconLoader.getIcon("/welcome/register.png"); // 32x32 + public static final Icon RemoveRecentProject = IconLoader.getIcon("/welcome/project/remove.png"); // 10x10 + public static final Icon RemoveRecentProjectHover = IconLoader.getIcon("/welcome/project/remove-hover.png"); // 10x10 + } public static class Xml { diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 3baa8c859b77..98a4c350a07c 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -385,6 +385,14 @@ public class UIUtil { } } + public static boolean isRetina (GraphicsDevice device) { + if (SystemInfo.isMac && SystemInfo.isJavaVersionAtLeast("1.7")) { + return DetectRetinaKit.isOracleMacRetinaDevice(device); + } else { + return isRetina(); + } + } + //public static boolean isMacRetina(Graphics2D g) { // return DetectRetinaKit.isMacRetina(g); //} diff --git a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java index 9a78602ac8de..4c7031ffbc1b 100644 --- a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java +++ b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java @@ -52,9 +52,13 @@ public class PatchReader { @NonNls private static final Pattern ourContextAfterHunkStartPattern = Pattern.compile("--- (\\d+),(\\d+) ----"); public PatchReader(CharSequence patchContent) { + this(patchContent, true); + } + + public PatchReader(CharSequence patchContent, boolean parseHunks) { myLines = LineTokenizer.tokenizeIntoList(patchContent, false); - myAdditionalInfoParser = new AdditionalInfoParser(); - myPatchContentParser = new PatchContentParser(); + myAdditionalInfoParser = new AdditionalInfoParser(!parseHunks); + myPatchContentParser = new PatchContentParser(parseHunks); } public List readAllPatches() throws PatchSyntaxException { @@ -169,10 +173,12 @@ public class PatchReader { private static class AdditionalInfoParser implements Parser { // first is path! private final Map> myResultMap; + private final boolean myIgnoreMode; private Map myAddMap; private PatchSyntaxException mySyntaxException; - private AdditionalInfoParser() { + private AdditionalInfoParser(boolean ignore) { + myIgnoreMode = ignore; myAddMap = new HashMap(); myResultMap = new HashMap>(); } @@ -194,12 +200,16 @@ public class PatchReader { @Override public boolean testIsStart(String start) { - if (mySyntaxException != null) return false; // stop on first error + if (myIgnoreMode || mySyntaxException != null) return false; // stop on first error return start != null && start.contains(UnifiedDiffWriter.ADDITIONAL_PREFIX); } @Override public void parse(String start, ListIterator iterator) { + if (myIgnoreMode) { + return; + } + if (! iterator.hasNext()) { mySyntaxException = new PatchSyntaxException(iterator.previousIndex(), "Empty additional info header"); return; @@ -244,13 +254,15 @@ public class PatchReader { private static class PatchContentParser implements Parser { + private final boolean myParseHunks; private DiffFormat myDiffFormat = null; private final List myPatches; private boolean myDiffCommandLike; private boolean myIndexLike; - private PatchContentParser() { + private PatchContentParser(boolean parseHunks) { + myParseHunks = parseHunks; myPatches = new SmartList(); } @@ -302,7 +314,7 @@ public class PatchReader { } extractFileName(curLine, curPatch, false, myDiffCommandLike && myIndexLike); - while (iterator.hasNext()) { + while (myParseHunks && iterator.hasNext()) { PatchHunk hunk; if (myDiffFormat == DiffFormat.UNIFIED) { hunk = readNextHunkUnified(iterator); diff --git a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextFilePatch.java b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextFilePatch.java index b6442a7c89a1..804b066b070a 100644 --- a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextFilePatch.java +++ b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextFilePatch.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.diff.impl.patch; +import org.jetbrains.annotations.Nullable; + import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; @@ -24,7 +26,7 @@ import java.util.List; * @author yole */ public class TextFilePatch extends FilePatch { - private Charset myCharset; + @Nullable private Charset myCharset; private final List myHunks; public void addHunk(final PatchHunk hunk) { @@ -35,7 +37,7 @@ public class TextFilePatch extends FilePatch { return Collections.unmodifiableList(myHunks); } - public TextFilePatch(Charset charset) { + public TextFilePatch(@Nullable Charset charset) { myCharset = charset; myHunks = new ArrayList(); } @@ -65,11 +67,16 @@ public class TextFilePatch extends FilePatch { return myHunks.size() == 1 && myHunks.get(0).isDeletedContent(); } + @Nullable public Charset getCharset() { return myCharset; } - public void setCharset(Charset charset) { + /** + * To be removed in IDEA 15 + */ + @Deprecated + public void setCharset(@Nullable Charset charset) { myCharset = charset; } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java index 96bb835bc086..461d58d52d48 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java @@ -665,10 +665,26 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD notifyStateChanged(); } - // todo problem: control usage - public static List loadPatches(Project project, final String patchPath, CommitContext commitContext) throws IOException, PatchSyntaxException { + @NotNull + public static List loadPatches(Project project, + final String patchPath, + CommitContext commitContext) throws IOException, PatchSyntaxException { + return loadPatches(project, patchPath, commitContext, true); + } + + @NotNull + static List loadPatchesWithoutContent(Project project, + final String patchPath, + CommitContext commitContext) throws IOException, PatchSyntaxException { + return loadPatches(project, patchPath, commitContext, false); + } + + private static List loadPatches(Project project, + final String patchPath, + CommitContext commitContext, + boolean loadContent) throws IOException, PatchSyntaxException { char[] text = FileUtil.loadFileText(new File(patchPath), CharsetToolkit.UTF8); - PatchReader reader = new PatchReader(new CharArrayCharSequence(text)); + PatchReader reader = new PatchReader(new CharArrayCharSequence(text), loadContent); final List textFilePatches = reader.readAllPatches(); final TransparentlyFailedValueI>, PatchSyntaxException> additionalInfo = reader.getAdditionalInfo( null); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangeList.java index af3bb540d65e..e88ce0885733 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangeList.java @@ -24,7 +24,6 @@ package com.intellij.openapi.vcs.changes.shelf; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.patch.FilePatch; -import com.intellij.openapi.diff.impl.patch.TextFilePatch; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.DefaultJDOMExternalizer; import com.intellij.openapi.util.InvalidDataException; @@ -109,7 +108,7 @@ public class ShelvedChangeList implements JDOMExternalizable { public List getChanges(Project project) { if (myChanges == null) { try { - final List list = ShelveChangesManager.loadPatches(project, PATH, null); + final List list = ShelveChangesManager.loadPatchesWithoutContent(project, PATH, null); myChanges = new ArrayList(); for (FilePatch patch : list) { FileStatus status; diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java index c7da2ad49a04..a31a76e73fa6 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java @@ -60,7 +60,7 @@ public class VcsTestUtil { * @param name Name of the directory. * @return reference to the created or already existing directory. */ - public static VirtualFile createDir(@NotNull final Project project, @NotNull final VirtualFile parent, @NotNull final String name) { + public static VirtualFile findOrCreateDir(@NotNull final Project project, @NotNull final VirtualFile parent, @NotNull final String name) { return new WriteCommandAction(project) { @Override protected void run(@NotNull Result result) throws Throwable { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java index 65a6fa82f5f9..6e33a76aecff 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.colors.EditorColorsListener; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; @@ -194,7 +195,7 @@ public class ExecutionPointHighlighter { if (myRangeHighlighter != null) return; EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); - myRangeHighlighter = myEditor.getMarkupModel().addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, + myRangeHighlighter = DocumentMarkupModel.forDocument(document, myProject, true).addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, myNotTopFrame ? scheme.getAttributes(DebuggerColors.NOT_TOP_FRAME_ATTRIBUTES) : scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES)); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java index bfa26c048ea8..b561e32d51a9 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java @@ -109,7 +109,7 @@ public class HtmlTagCanBeJavadocTagInspection extends BaseInspection { } private static void appendElementText(String text, int startOffset, int endOffset, StringBuilder out) { - if (out.length() == 6 && endOffset - startOffset > 0 && !Character.isWhitespace(text.charAt(startOffset))) { + if (out.length() == "{@code".length() && endOffset - startOffset > 0 && !Character.isWhitespace(text.charAt(startOffset))) { out.append(' '); } out.append(text, startOffset, endOffset); diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 19b2f20d7054..2d858e573247 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -217,22 +217,31 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { return isInCoverageScope(psiPackage); } })) { - final PsiElement[] childElements = ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiElement[] compute() { - return psiPackage.getChildren(mySuitesBundle.getSearchScope(node.getProject())); + final PsiPackage[] subPackages = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiPackage[] compute() { + return psiPackage.getSubPackages(mySuitesBundle.getSearchScope(node.getProject())); } }); - for (PsiElement element : childElements) { - if (element instanceof PsiClass) { - PsiClass aClass = (PsiClass) element; - if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; - children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); + for (PsiPackage subPackage: subPackages) { + processSubPackage(subPackage, children); + } + + final PsiFile[] childFiles = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiFile[] compute() { + return psiPackage.getFiles(mySuitesBundle.getSearchScope(node.getProject())); } - else if (element instanceof PsiPackage) { - processSubPackage((PsiPackage) element, children); + }); + for (PsiFile file : childFiles) { + if (file instanceof PsiJavaFile) { + PsiClass[] classes = ((PsiJavaFile)file).getClasses(); + if (classes.length > 0) { + PsiClass aClass = classes[0]; + if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; + children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); + } } - else if (element instanceof PsiNamedElement) { - children.add(new CoverageListNode(myProject, (PsiNamedElement) element, mySuitesBundle, myStateBean)); + else { + children.add(new CoverageListNode(myProject, file, mySuitesBundle, myStateBean)); } } } diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 64497ddbd505..3fe591e38d62 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -138,6 +138,7 @@ public abstract class GitHandler { } myCommandLine.addParameter(command.name()); myStdoutSuppressed = true; + mySilent = myCommand.lockingPolicy() == GitCommand.LockingPolicy.READ; } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index 5a577f024437..3fdaa5bd8b77 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -481,6 +481,8 @@ public class GitImpl implements Git { @Override public GitLineHandler compute() { final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.FETCH); + h.setSilent(false); + h.setStdoutSuppressed(false); h.setUrl(url); h.addParameters(remote); h.addParameters(params); diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 9d1e27395ca0..c9824aeec26f 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -40,12 +40,7 @@ import com.intellij.vcs.log.*; import com.intellij.vcs.log.impl.HashImpl; import com.intellij.vcs.log.impl.LogDataImpl; import com.intellij.vcs.log.util.StopWatch; -import git4idea.GitBranch; -import git4idea.GitCommit; -import git4idea.GitFileRevision; -import git4idea.GitRevisionNumber; -import git4idea.GitUtil; -import git4idea.GitVcs; +import git4idea.*; import git4idea.branch.GitBranchUtil; import git4idea.commands.*; import git4idea.config.GitVersionSpecialty; @@ -740,7 +735,7 @@ public class GitHistoryUtils { if (factory == null) { return LogDataImpl.empty(); } - final Set refs = new OpenTHashSet(GitLogProvider.REF_ONLY_NAME_STRATEGY); + final Set refs = new OpenTHashSet(GitLogProvider.DONT_CONSIDER_SHA); final List commits = loadDetails(project, root, withRefs, false, new NullableFunction() { @Nullable diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties index a2937584ec39..a48c05400bf3 100644 --- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties +++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties @@ -256,7 +256,7 @@ rebase.editor.button=Start Rebasing rebase.editor.comment.column=Comment rebase.editor.commit.column=Commit rebase.editor.invalid.entryset=No commits found to rebase -rebase.editor.invalid.squash=The first non-skip commit could not be marked as squashed since squash merges commit with the previous commit. +rebase.editor.invalid.squash=The first non-skip commit can't be marked as {0} since it merges commit with the previous commit. rebase.editor.message=Reorder and edit &rebased commits rebase.editor.move.down.tooltip=Move commit down (commit will be applied later) rebase.editor.move.down=Move &Down diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index 59e3babe372d..3c4e0a3034c7 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -55,15 +55,15 @@ public class GitLogProvider implements VcsLogProvider { return ref.getType() == GitRefManager.TAG ? ref.getName() : null; } }; - public static final TObjectHashingStrategy REF_ONLY_NAME_STRATEGY = new TObjectHashingStrategy() { + public static final TObjectHashingStrategy DONT_CONSIDER_SHA = new TObjectHashingStrategy() { @Override public int computeHashCode(@NotNull VcsRef ref) { - return ref.getName().hashCode(); + return 31 * ref.getName().hashCode() + ref.getType().hashCode(); } @Override public boolean equals(@NotNull VcsRef ref1, @NotNull VcsRef ref2) { - return ref1.getName().equals(ref2.getName()); + return ref1.getName().equals(ref2.getName()) && ref1.getType().equals(ref2.getType()); } }; @@ -104,7 +104,7 @@ public class GitLogProvider implements VcsLogProvider { DetailedLogData data = GitHistoryUtils.loadMetadata(myProject, root, true, params); Set safeRefs = data.getRefs(); - Set allRefs = new OpenTHashSet(safeRefs, REF_ONLY_NAME_STRATEGY); + Set allRefs = new OpenTHashSet(safeRefs, DONT_CONSIDER_SHA); Set branches = readBranches(repository); addNewElements(allRefs, branches); diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java index e3c9a1aa80c2..e0c9aa035257 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java @@ -19,6 +19,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.ListWithSelection; @@ -167,8 +168,9 @@ public class GitRebaseEditor extends DialogWrapper { while (i < entries.size() && entries.get(i).getAction() == GitRebaseEntry.Action.skip) { i++; } - if (i < entries.size() && entries.get(i).getAction() == GitRebaseEntry.Action.squash) { - setErrorText(GitBundle.getString("rebase.editor.invalid.squash")); + GitRebaseEntry.Action action = entries.get(i).getAction(); + if (i < entries.size() && (action == GitRebaseEntry.Action.squash || action == GitRebaseEntry.Action.fixup)) { + setErrorText(GitBundle.message("rebase.editor.invalid.squash", StringUtil.toLowerCase(action.name()))); setOKActionEnabled(false); return; } diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseLineListener.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseLineListener.java index 62aabee3a3bc..941c39357fb7 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseLineListener.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseLineListener.java @@ -69,7 +69,7 @@ public class GitRebaseLineListener extends GitLineHandlerAdapter { assert myStatus == null; myStatus = myProgressLine == null ? Status.CANCELLED : Status.ERROR; } - else if (line.startsWith("fatal") || line.startsWith("error: ") || line.startsWith("Cannot rebase")) { + else if (line.startsWith("fatal") || line.startsWith("error: ") || line.startsWith("Cannot")) { if (myStatus != Status.CONFLICT) { myStatus = Status.ERROR; } diff --git a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java index f4afb51a8e21..2b086f459cf1 100644 --- a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java +++ b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java @@ -136,6 +136,29 @@ public class GitLogProviderTest extends GitSingleRepoTest { })); } + public void test_support_equally_named_branch_and_tag() throws Exception { + prepareSomeHistory(); + git("branch build"); + git("tag build"); + + VcsLogProvider.DetailedLogData data = myLogProvider.readFirstBlock(myProjectRoot, + new RequirementsImpl(1000, true, Collections.emptySet())); + List expectedLog = log(); + assertOrderedEquals(data.getCommits(), expectedLog); + assertTrue(ContainerUtil.exists(data.getRefs(), new Condition() { + @Override + public boolean value(VcsRef ref) { + return ref.getName().equals("build") && ref.getType() == GitRefManager.LOCAL_BRANCH; + } + })); + assertTrue(ContainerUtil.exists(data.getRefs(), new Condition() { + @Override + public boolean value(VcsRef ref) { + return ref.getName().equals("build") && ref.getType() == GitRefManager.TAG; + } + })); + } + private static void prepareSomeHistory() { tac("a.txt"); git("tag ATAG"); diff --git a/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java b/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java index 39eacd86883a..e5259354ba7f 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java +++ b/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -222,7 +222,7 @@ public abstract class GitChangeProviderTest extends GitSingleRepoTest { private VirtualFile create(VirtualFile parent, String name, boolean dir) { final VirtualFile file = dir ? - VcsTestUtil.createDir(myProject, parent, name) : + VcsTestUtil.findOrCreateDir(myProject, parent, name) : createFile(myProject, parent, name, "content" + Math.random()); dirty(file); return file; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java index 398498f87e6a..32ede785af15 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java @@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy.util; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; @@ -132,14 +133,16 @@ public class LibrariesUtil { @Nullable public static String getGroovyHomePath(@NotNull Module module) { - final VirtualFile local = findJarWithClass(module, SOME_GROOVY_CLASS); - if (local != null) { - final VirtualFile parent = local.getParent(); - if (parent != null) { - if (("lib".equals(parent.getName()) || "embeddable".equals(parent.getName())) && parent.getParent() != null) { - return parent.getParent().getPath(); + if (!DumbService.isDumb(module.getProject())) { + final VirtualFile local = findJarWithClass(module, SOME_GROOVY_CLASS); + if (local != null) { + final VirtualFile parent = local.getParent(); + if (parent != null) { + if (("lib".equals(parent.getName()) || "embeddable".equals(parent.getName())) && parent.getParent() != null) { + return parent.getParent().getPath(); + } + return parent.getPath(); } - return parent.getPath(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java index cfba473139b1..be2e8315d780 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java @@ -29,15 +29,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.impl.source.javadoc.PsiDocParamRef; -import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -68,7 +64,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author ven @@ -76,7 +71,6 @@ import java.util.Map; public class GroovyDocumentationProvider implements CodeDocumentationProvider, ExternalDocumentationProvider { private static final String LINE_SEPARATOR = "\n"; - @NonNls private static final String PARAM_TAG = "@param"; @NonNls private static final String RETURN_TAG = "@return"; @NonNls private static final String THROWS_TAG = "@throws"; private static final String BODY_HTML = ""; @@ -248,61 +242,14 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E aClass.isInterface() ? "interface" : aClass instanceof PsiTypeParameter ? "type parameter" : aClass.isEnum() ? "enum" : "class"; buffer.append(classString).append(" ").append(aClass.getName()); - if (aClass.hasTypeParameters()) { - PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); + JavaDocumentationProvider.generateTypeParameters(aClass, buffer); - buffer.append("<"); - - for (int i = 0; i < typeParameters.length; i++) { - if (i > 0) buffer.append(", "); - - PsiTypeParameter tp = typeParameters[i]; - - buffer.append(tp.getName()); - - PsiClassType[] refs = tp.getExtendsListTypes(); - - if (refs.length > 0) { - buffer.append(" extends "); - - for (int j = 0; j < refs.length; j++) { - if (j > 0) buffer.append(" & "); - PsiImplUtil.appendTypeString(buffer, refs[j], aClass); - } - } - } - - buffer.append(">"); - } - - PsiClassType[] refs = aClass.getExtendsListTypes(); - if (refs.length > 0 || !aClass.isInterface() && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { - buffer.append(" extends "); - if (refs.length == 0) { - buffer.append("Object"); - } - else { - for (int i = 0; i < refs.length; i++) { - if (i > 0) buffer.append(", "); - PsiImplUtil.appendTypeString(buffer, refs[i], aClass); - } - } - } - - refs = aClass.getImplementsListTypes(); - if (refs.length > 0) { - buffer.append("\nimplements "); - for (int i = 0; i < refs.length; i++) { - if (i > 0) buffer.append(", "); - PsiImplUtil.appendTypeString(buffer, refs[i], aClass); - - } - } + JavaDocumentationProvider.writeExtends(aClass, buffer, aClass.getExtendsListTypes()); + JavaDocumentationProvider.writeImplements(aClass, buffer, aClass.getImplementsListTypes()); return buffer.toString(); } - public static void appendTypeString(@NotNull StringBuilder buffer, @Nullable PsiType type, PsiElement context) { if (type instanceof GrTraitType) { generateTraitType(buffer, ((GrTraitType)type), context); @@ -546,44 +493,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E try { if (owner instanceof GrMethod) { final GrMethod method = (GrMethod)owner; - final GrParameter[] parameters = method.getParameters(); - final Map param2Description = new HashMap(); - final PsiMethod[] superMethods = method.findSuperMethods(); - - for (PsiMethod superMethod : superMethods) { - final PsiDocComment comment = superMethod.getDocComment(); - if (comment != null) { - final PsiDocTag[] params = comment.findTagsByName("param"); - for (PsiDocTag param : params) { - final PsiElement[] dataElements = param.getDataElements(); - if (dataElements != null) { - String paramName = null; - for (PsiElement dataElement : dataElements) { - if (dataElement instanceof PsiDocParamRef) { - paramName = dataElement.getReference().getCanonicalText(); - break; - } - } - if (paramName != null) { - param2Description.put(paramName, param.getText()); - } - } - } - } - } - for (PsiParameter parameter : parameters) { - String description = param2Description.get(parameter.getName()); - if (description != null) { - builder.append(CodeDocumentationUtil.createDocCommentLine("", project, commenter)); - if (description.indexOf('\n') > -1) description = description.substring(0, description.lastIndexOf('\n')); - builder.append(description); - } - else { - builder.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); - builder.append(parameter.getName()); - } - builder.append(LINE_SEPARATOR); - } + JavaDocumentationProvider.generateParametersTakingDocFromSuperMethods(project, builder, commenter, method); final PsiType returnType = method.getInferredReturnType(); if ((returnType != null || method.getModifierList().hasModifierProperty(GrModifier.DEF)) && @@ -602,7 +512,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E else if (owner instanceof GrTypeDefinition) { final PsiTypeParameterList typeParameterList = ((PsiClass)owner).getTypeParameterList(); if (typeParameterList != null) { - createTypeParamsListComment(builder, project, commenter, typeParameterList); + JavaDocumentationProvider.createTypeParamsListComment(builder, project, commenter, typeParameterList); } } return builder.length() > 0 ? builder.toString() : null; @@ -611,17 +521,4 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E StringBuilderSpinAllocator.dispose(builder); } } - - private static void createTypeParamsListComment(final StringBuilder buffer, - final Project project, - final CodeDocumentationAwareCommenter commenter, - final PsiTypeParameterList typeParameterList) { - final PsiTypeParameter[] typeParameters = typeParameterList.getTypeParameters(); - for (PsiTypeParameter typeParameter : typeParameters) { - buffer.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); - buffer.append("<").append(typeParameter.getName()).append(">"); - buffer.append(LINE_SEPARATOR); - } - } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java index 8aea83070925..1c9bc0e95de8 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java @@ -78,7 +78,7 @@ public class HgTaskHandler extends DvcsTaskHandler { Project project = repository.getProject(); VirtualFile repositoryRoot = repository.getRoot(); try { - new HgCommitCommand(project, repositoryRoot, "Automated merge with " + branch).execute(); + new HgCommitCommand(project, repository, "Automated merge with " + branch).execute(); new HgBookmarkCommand(project, repositoryRoot, branch).deleteBookmark(); } catch (HgCommandException e) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java index 4ba12ee4add0..7ff85c106bfa 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java @@ -18,7 +18,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; @@ -30,9 +29,7 @@ import org.zmlx.hg4idea.HgVcsMessages; import org.zmlx.hg4idea.execution.HgCommandException; import org.zmlx.hg4idea.execution.HgCommandExecutor; import org.zmlx.hg4idea.repo.HgRepository; -import org.zmlx.hg4idea.repo.HgRepositoryManager; import org.zmlx.hg4idea.util.HgEncodingUtil; -import org.zmlx.hg4idea.util.HgUtil; import java.io.File; import java.io.IOException; @@ -49,7 +46,7 @@ public class HgCommitCommand { private static final String TEMP_FILE_NAME = ".hg4idea-commit.tmp"; private final Project myProject; - private final VirtualFile myRoot; + private final HgRepository myRepository; private final String myMessage; @NotNull private final Charset myCharset; private final boolean myAmend; @@ -58,21 +55,21 @@ public class HgCommitCommand { private Set myFiles = Collections.emptySet(); @NotNull private List mySubrepos = Collections.emptyList(); - public HgCommitCommand(@NotNull Project project, @NotNull VirtualFile root, String message, boolean amend, boolean closeBranch) { + public HgCommitCommand(@NotNull Project project, @NotNull HgRepository repository, String message, boolean amend, boolean closeBranch) { myProject = project; - myRoot = root; + myRepository = repository; myMessage = message; myCharset = HgEncodingUtil.getDefaultCharset(myProject); myAmend = amend; myCloseBranch = closeBranch; } - public HgCommitCommand(@NotNull Project project, @NotNull VirtualFile root, String message, boolean amend) { - this(project, root, message, amend, false); + public HgCommitCommand(@NotNull Project project, @NotNull HgRepository repo, String message, boolean amend) { + this(project, repo, message, amend, false); } - public HgCommitCommand(Project project, @NotNull VirtualFile root, String message) { - this(project, root, message, false); + public HgCommitCommand(Project project, @NotNull HgRepository repo, String message) { + this(project, repo, message, false); } public void setFiles(@NotNull Set files) { @@ -110,10 +107,7 @@ public class HgCommitCommand { commitChunkFiles(chunk, amendCommit, false, myCloseBranch && i == size - 1); } } - if (!myProject.isDisposed()) { - HgRepositoryManager manager = HgUtil.getRepositoryManager(myProject); - manager.updateRepository(myRoot); - } + myRepository.update(); final MessageBus messageBus = myProject.getMessageBus(); messageBus.syncPublisher(HgVcs.REMOTE_TOPIC).update(myProject, null); messageBus.syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null); @@ -125,8 +119,6 @@ public class HgCommitCommand { private void commitChunkFiles(@NotNull List chunk, boolean amendCommit, boolean withSubrepos, boolean closeBranch) throws VcsException { - HgRepository repository = HgUtil.getRepositoryForFile(myProject, myRoot); - assert repository != null; List parameters = new LinkedList(); parameters.add("--logfile"); parameters.add(saveCommitMessage().getAbsolutePath()); @@ -139,7 +131,7 @@ public class HgCommitCommand { parameters.add("--amend"); } if (closeBranch) { - if (chunk.isEmpty() && repository.getState() != Repository.State.MERGING) { + if (chunk.isEmpty() && myRepository.getState() != Repository.State.MERGING) { //if there are changed files but nothing selected -> need to exclude all; if merge commit then nothing excluded parameters.add("-X"); parameters.add("\"**\""); @@ -149,7 +141,7 @@ public class HgCommitCommand { parameters.addAll(chunk); HgCommandExecutor executor = new HgCommandExecutor(myProject); executor.setCharset(myCharset); - ensureSuccess(executor.executeInCurrentThread(myRoot, "commit", parameters)); + ensureSuccess(executor.executeInCurrentThread(myRepository.getRoot(), "commit", parameters)); } private File saveCommitMessage() throws VcsException { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index fe13294ef8ab..94c37209a557 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -104,7 +104,7 @@ public class HgCheckinEnvironment implements CheckinEnvironment { HgRepository repo = entry.getKey(); Set selectedFiles = entry.getValue(); HgCommitCommand command = - new HgCommitCommand(myProject, repo.getRoot(), preparedComment, myNextCommitAmend, myCloseBranch); + new HgCommitCommand(myProject, repo, preparedComment, myNextCommitAmend, myCloseBranch); if (isMergeCommit(repo.getRoot())) { //partial commits are not allowed during merges diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java index 5527efd32226..aa1a7c432e70 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java @@ -12,6 +12,7 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; @@ -43,6 +44,7 @@ public class HgRegularUpdater implements HgUpdater { @NotNull private final Project project; @NotNull private final VirtualFile repoRoot; @NotNull private final HgUpdateConfigurationSettings updateConfiguration; + private static final Logger LOG = Logger.getInstance(HgRegularUpdater.class); public HgRegularUpdater(@NotNull Project project, @NotNull VirtualFile repository, @NotNull HgUpdateConfigurationSettings configuration) { this.project = project; @@ -185,14 +187,21 @@ public class HgRegularUpdater implements HgUpdater { private void commitOrWarnAboutConflicts(List exceptions, HgCommandResult mergeResult) throws VcsException { if (mergeResult.getExitValue() == 0) { //operation successful and no conflicts try { - new HgCommitCommand(project, repoRoot, "Automated merge").execute(); - } catch (HgCommandException e) { + HgRepository hgRepository = HgUtil.getRepositoryForFile(project, repoRoot); + if (hgRepository == null) { + LOG.warn("Couldn't find repository info for " + repoRoot.getName()); + return; + } + new HgCommitCommand(project, hgRepository, "Automated merge").execute(); + } + catch (HgCommandException e) { throw new VcsException(e); } - } else { - reportWarning(exceptions, HgVcsMessages.message("hg4idea.update.warning.merge.conflicts", repoRoot.getPath())); - } } + else { + reportWarning(exceptions, HgVcsMessages.message("hg4idea.update.warning.merge.conflicts", repoRoot.getPath())); + } + } private HgCommandResult doMerge(ProgressIndicator indicator) throws VcsException { indicator.setText2(HgVcsMessages.message("hg4idea.update.progress.merging")); diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java index 7c41b93e806e..009f90c9a58a 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java @@ -22,6 +22,8 @@ import org.zmlx.hg4idea.HgFileRevision; import org.zmlx.hg4idea.command.HgCommitCommand; import org.zmlx.hg4idea.command.HgLogCommand; import org.zmlx.hg4idea.execution.HgCommandException; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.repo.HgRepositoryImpl; import java.util.List; @@ -37,7 +39,8 @@ public class HgEncodingTest extends HgPlatformTest { public void testCommitUtfMessage() throws HgCommandException, VcsException { cd(myRepository); echo("file.txt", "lalala"); - HgCommitCommand commitCommand = new HgCommitCommand(myProject, myRepository, "сообщение"); + HgRepository hgRepo = HgRepositoryImpl.getInstance(myRepository, myProject, myProject); + HgCommitCommand commitCommand = new HgCommitCommand(myProject, hgRepo, "сообщение"); commitCommand.execute(); } @@ -47,7 +50,8 @@ public class HgEncodingTest extends HgPlatformTest { String fileName = "file.txt"; echo(fileName, "lalala"); String comment = "öäüß"; - HgCommitCommand commitCommand = new HgCommitCommand(myProject, myRepository, comment); + HgRepository hgRepo = HgRepositoryImpl.getInstance(myRepository, myProject, myProject); + HgCommitCommand commitCommand = new HgCommitCommand(myProject, hgRepo, comment); commitCommand.execute(); HgLogCommand logCommand = new HgLogCommand(myProject); myRepository.refresh(false, true); diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java index 7099c3bbf88d..28d69f9340ac 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java @@ -107,6 +107,7 @@ public abstract class HgPlatformTest extends UsefulTestCase { File hgrc = new File(new File(repositoryRoot.getPath(), ".hg"), "hgrc"); FileUtil.appendToFile(hgrc, FileUtil.loadFile(hgrcFile)); assertTrue(hgrc.exists()); + repositoryRoot.refresh(false, true); } protected static void appendToHgrc(@NotNull VirtualFile repositoryRoot, @NotNull String text) throws IOException { diff --git a/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java b/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java index 81387d18735b..36fe33f8d9b6 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java @@ -23,6 +23,8 @@ import org.zmlx.hg4idea.HgFileRevision; import org.zmlx.hg4idea.command.HgCommitCommand; import org.zmlx.hg4idea.command.HgLogCommand; import org.zmlx.hg4idea.execution.HgCommandException; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.repo.HgRepositoryImpl; import java.util.List; @@ -51,7 +53,8 @@ public class HgCommitTest extends HgPlatformTest { logCommand.setLogFile(false); HgFile hgFile = new HgFile(myRepository, VfsUtilCore.virtualToIoFile(myRepository)); List revisions = logCommand.execute(hgFile, -1, false); - HgCommitCommand commit = new HgCommitCommand(myProject, myRepository, changedCommit, true); + HgRepository hgRepo = HgRepositoryImpl.getInstance(myRepository, myProject, myProject); + HgCommitCommand commit = new HgCommitCommand(myProject, hgRepo, changedCommit, true); commit.execute(); List revisionsAfterAmendCommit = logCommand.execute(hgFile, -1, false); assertTrue(revisions.size() == revisionsAfterAmendCommit.size()); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 984781451cb7..612255f42450 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -161,7 +161,7 @@ public class ClassWriter { DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); int startLine = tracer != null ? tracer.getCurrentSourceLine() : 0; - BytecodeMappingTracer dummy_tracer = new BytecodeMappingTracer(); + BytecodeMappingTracer dummy_tracer = new BytecodeMappingTracer(startLine); try { // last minute processing @@ -184,6 +184,8 @@ public class ClassWriter { // fields boolean enumFields = false; + dummy_tracer.incrementCurrentSourceLine(buffer.countLines(start_class_def)); + for (StructField fd : cl.getFields()) { boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); @@ -193,6 +195,7 @@ public class ClassWriter { if (isEnum) { if (enumFields) { buffer.append(',').appendLineSeparator(); + dummy_tracer.incrementCurrentSourceLine(); } enumFields = true; } @@ -200,6 +203,7 @@ public class ClassWriter { buffer.append(';'); buffer.appendLineSeparator(); buffer.appendLineSeparator(); + dummy_tracer.incrementCurrentSourceLine(2); enumFields = false; } @@ -210,6 +214,7 @@ public class ClassWriter { if (enumFields) { buffer.append(';').appendLineSeparator(); + dummy_tracer.incrementCurrentSourceLine(); } // FIXME: fields don't matter at the moment @@ -383,6 +388,7 @@ public class ClassWriter { } private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { + int start = buffer.length(); boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); boolean isDeprecated = fd.getAttributes().containsKey("Deprecated"); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); @@ -430,6 +436,8 @@ public class ClassWriter { buffer.append(fd.getName()); + tracer.incrementCurrentSourceLine(buffer.countLines(start)); + Exprent initializer; if (fd.hasModifier(CodeConstants.ACC_STATIC)) { initializer = wrapper.getStaticFieldInitializers().getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); @@ -461,6 +469,7 @@ public class ClassWriter { if (!isEnum) { buffer.append(";").appendLineSeparator(); + tracer.incrementCurrentSourceLine(); } } @@ -771,6 +780,8 @@ public class ClassWriter { } } + tracer.incrementCurrentSourceLine(buffer.countLines(start_index_method)); + if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { // native or abstract method (explicit or interface) if (isAnnotation) { StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault"); @@ -782,6 +793,7 @@ public class ClassWriter { buffer.append(';'); buffer.appendLineSeparator(); + tracer.incrementCurrentSourceLine(); } else { if (!clinit && !dinit) { @@ -793,12 +805,12 @@ public class ClassWriter { buffer.setCurrentLine(lineNumberTable.getFirstLine() - 1); } buffer.append('{').appendLineSeparator(); + tracer.incrementCurrentSourceLine(); RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root; if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence try { - tracer.incrementCurrentSourceLine(buffer.countLines(start_index_method)); int startLine = tracer.getCurrentSourceLine(); TextBuffer code = root.toJava(indent + 1, tracer); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java index 2016f08b306b..93e51939507a 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java @@ -307,7 +307,12 @@ public class TextBuffer { if (lineMapping.length > 0) { myLineMapping = new HashMap(); for (int i = 0; i < lineMapping.length; i+=2) { - myLineMapping.put(lineMapping[i+1], lineMapping[i]); + int key = lineMapping[i + 1]; + int value = lineMapping[i]; + Integer existing = myLineMapping.get(key); + if (existing == null || value < existing) { + myLineMapping.put(key, value); + } } } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java index 70ea2bc2b575..26cec6227c94 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java @@ -85,6 +85,7 @@ public class VarExprent extends Exprent { if (classDef) { ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(varType.value); new ClassWriter().classToJava(child, buffer, indent, tracer); + tracer.incrementCurrentSourceLine(buffer.countLines()); } else { String name = null; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java index 1c028d018e36..4a5eb1333703 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java @@ -256,14 +256,13 @@ public class IfStatement extends Statement { elseif = true; } else { - BytecodeMappingTracer else_tracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine()); + BytecodeMappingTracer else_tracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine() + 1); TextBuffer content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, else_tracer); if (content.length() > 0) { buf.appendIndent(indent).append("} else {").appendLineSeparator(); - else_tracer.shiftSourceLines(1); - tracer.setCurrentSourceLine(else_tracer.getCurrentSourceLine() + 1); + tracer.setCurrentSourceLine(else_tracer.getCurrentSourceLine()); tracer.addTracer(else_tracer); buf.append(content); diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java deleted file mode 100644 index a258ca014161..000000000000 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.java.decompiler; - -import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class BytecodeToSourceMappingTest extends SingleClassesTestBase { - @Override - protected Map getDecompilerOptions() { - return new HashMap() {{ - put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); - }}; - } - - @Test public void testSimpleBytecodeMapping() { doTest("pkg/TestClassSimpleBytecodeMapping"); } - @Test public void testSynchronizedMapping() { doTest("pkg/TestSynchronizedMapping"); } -} diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index c1b36def4c82..8a51c728cb4a 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -15,9 +15,21 @@ */ package org.jetbrains.java.decompiler; +import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.junit.Test; +import java.util.HashMap; +import java.util.Map; + public class SingleClassesTest extends SingleClassesTestBase { + @Override + protected Map getDecompilerOptions() { + return new HashMap() {{ + put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); + put(IFernflowerPreferences.DUMP_ORIGINAL_LINES, "1"); + }}; + } + @Test public void testClassFields() { doTest("pkg/TestClassFields"); } @Test public void testClassLambda() { doTest("pkg/TestClassLambda"); } @Test public void testClassLoop() { doTest("pkg/TestClassLoop"); } @@ -39,4 +51,10 @@ public class SingleClassesTest extends SingleClassesTestBase { @Test public void testTryCatchFinally() { doTest("pkg/TestTryCatchFinally"); } @Test public void testAmbiguousCall() { doTest("pkg/TestAmbiguousCall"); } @Test public void testAmbiguousCallWithDebugInfo() { doTest("pkg/TestAmbiguousCallWithDebugInfo"); } + @Test public void testSimpleBytecodeMapping() { doTest("pkg/TestClassSimpleBytecodeMapping"); } + @Test public void testSynchronizedMapping() { doTest("pkg/TestSynchronizedMapping"); } + @Test public void testAbstractMethods() { doTest("pkg/TestAbstractMethods"); } + @Test public void testLocalClass() { doTest("pkg/TestLocalClass"); } + @Test public void testAnonymousClass() { doTest("pkg/TestAnonymousClass"); } + @Test public void testThrowException() { doTest("pkg/TestThrowException"); } } diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAbstractMethods.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAbstractMethods.class new file mode 100644 index 000000000000..12ff5b20d869 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAbstractMethods.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$1.class new file mode 100644 index 000000000000..ff5e5878409d Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$1.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$2.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$2.class new file mode 100644 index 000000000000..536f320ed1c9 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$2.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$3.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$3.class new file mode 100644 index 000000000000..cc8d377c9534 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$3.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$4.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$4.class new file mode 100644 index 000000000000..3ee643664627 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$4.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$I.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$I.class new file mode 100644 index 000000000000..48eb4edc1bd2 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$I.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$Inner$1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$Inner$1.class new file mode 100644 index 000000000000..798b358a7b36 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$Inner$1.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$Inner.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$Inner.class new file mode 100644 index 000000000000..2b3d4639c26b Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass$Inner.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass.class new file mode 100644 index 000000000000..a849cd60ab4c Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestAnonymousClass.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByAnno.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByAnno.class index dca17055a9f3..cb8f565061da 100644 Binary files a/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByAnno.class and b/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByAnno.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByComment.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByComment.class index c1da53c08db1..d6013ce5aa3d 100644 Binary files a/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByComment.class and b/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations$ByComment.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations.class index 29924d2b61a8..ab0eb0eb723d 100644 Binary files a/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations.class and b/plugins/java-decompiler/engine/testData/classes/pkg/TestDeprecations.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestLocalClass$1Local.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestLocalClass$1Local.class new file mode 100644 index 000000000000..7b5cd401171a Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestLocalClass$1Local.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestLocalClass.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestLocalClass.class new file mode 100644 index 000000000000..fc9073b3b1d1 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestLocalClass.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestThrowException$1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestThrowException$1.class new file mode 100644 index 000000000000..e626366787d3 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestThrowException$1.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestThrowException.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestThrowException.class new file mode 100644 index 000000000000..b6c514ab15de Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestThrowException.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestTryCatchFinally.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestTryCatchFinally.class index 244dfad62aca..229e1b9d193e 100644 Binary files a/plugins/java-decompiler/engine/testData/classes/pkg/TestTryCatchFinally.class and b/plugins/java-decompiler/engine/testData/classes/pkg/TestTryCatchFinally.class differ diff --git a/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec b/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec index 3b1bee4d20a9..24b7c852219b 100644 --- a/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec +++ b/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec @@ -13,14 +13,36 @@ class i implements bg { i(b var1, j var2) { this.b = var1; - this.a = var2; + this.a = var2;// 1 } public void a(c var1, k var2, boolean var3) { - File var4 = this.a.b().a(var1); - b.a(this.b).add(var4); + File var4 = this.a.b().a(var1);// 2 + b.a(this.b).add(var4);// 3 } public void a(a.a.a.a.c.b var1) { } } + +class 'a/a/a/a/e/f/i' { + method ' (La/a/a/a/e/f/b;La/a/a/a/c/j;)V' { + 2 14 + 7 15 + } + + method 'a (La/a/a/a/c/c;La/a/a/a/a/k;Z)V' { + 1 19 + 4 19 + a 19 + f 19 + 12 20 + 15 20 + 1a 20 + } +} + +Lines mapping: +1 <-> 16 +2 <-> 20 +3 <-> 21 diff --git a/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec b/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec new file mode 100644 index 000000000000..59b102744c55 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec @@ -0,0 +1,30 @@ +package pkg; + +public abstract class TestAbstractMethods { + public abstract void foo(); + + public int test(int var1) { + return var1;// 11 + } + + protected abstract void foo1(); + + public void test2(String var1) { + System.out.println(var1);// 17 + } +} + +class 'pkg/TestAbstractMethods' { + method 'test (I)I' { + 1 6 + } + + method 'test2 (Ljava/lang/String;)V' { + 0 12 + 4 12 + } +} + +Lines mapping: +11 <-> 7 +17 <-> 13 diff --git a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec index b335867ca75f..caeb41d8ed38 100644 --- a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec +++ b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec @@ -8,11 +8,35 @@ class TestAmbiguousCall { } void test() { - IllegalArgumentException var1 = new IllegalArgumentException(); - this.m1((RuntimeException)var1, "RE"); - this.m1(var1, "IAE"); - IllegalArgumentException var2 = new IllegalArgumentException(); - this.m1((RuntimeException)var2, "RE"); - this.m1((IllegalArgumentException)var2, "IAE"); + IllegalArgumentException var1 = new IllegalArgumentException();// 8 + this.m1((RuntimeException)var1, "RE");// 9 + this.m1(var1, "IAE");// 10 + IllegalArgumentException var2 = new IllegalArgumentException();// 12 + this.m1((RuntimeException)var2, "RE");// 13 + this.m1((IllegalArgumentException)var2, "IAE");// 14 } } + +class 'pkg/TestAmbiguousCall' { + method 'test ()V' { + 7 10 + a 11 + c 11 + 11 12 + 13 12 + 1d 13 + 20 14 + 22 14 + 27 15 + 2a 15 + 2c 15 + } +} + +Lines mapping: +8 <-> 11 +9 <-> 12 +10 <-> 13 +12 <-> 14 +13 <-> 15 +14 <-> 16 diff --git a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec index da3baa9663ad..6380d6db06a3 100644 --- a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec +++ b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec @@ -8,11 +8,35 @@ class TestAmbiguousCall { } void test() { - IllegalArgumentException iae = new IllegalArgumentException(); - this.m1((RuntimeException)iae, "RE"); - this.m1(iae, "IAE"); - IllegalArgumentException re = new IllegalArgumentException(); - this.m1((RuntimeException)re, "RE"); - this.m1((IllegalArgumentException)re, "IAE"); + IllegalArgumentException iae = new IllegalArgumentException();// 8 + this.m1((RuntimeException)iae, "RE");// 9 + this.m1(iae, "IAE");// 10 + IllegalArgumentException re = new IllegalArgumentException();// 12 + this.m1((RuntimeException)re, "RE");// 13 + this.m1((IllegalArgumentException)re, "IAE");// 14 } } + +class 'pkg/TestAmbiguousCall' { + method 'test ()V' { + 7 10 + a 11 + c 11 + 11 12 + 13 12 + 1d 13 + 20 14 + 22 14 + 27 15 + 2a 15 + 2c 15 + } +} + +Lines mapping: +8 <-> 11 +9 <-> 12 +10 <-> 13 +12 <-> 14 +13 <-> 15 +14 <-> 16 diff --git a/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec b/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec new file mode 100644 index 000000000000..18cfaefd1b39 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec @@ -0,0 +1,142 @@ +package pkg; + +public abstract class TestAnonymousClass { + public static final Runnable R3 = new Runnable() { + public void run() { + boolean var1 = true;// 28 + boolean var2 = true;// 29 + } + }; + public static final Runnable R = new Runnable() { + public void run() { + boolean var1 = true;// 45 + boolean var2 = true;// 46 + } + }; + public static final Runnable R1 = new Runnable() { + public void run() { + boolean var1 = true;// 53 + boolean var2 = true;// 54 + } + }; + + void foo(int var1) throws Exception { + if(var1 > 0) {// 10 + TestAnonymousClass.I var2 = new TestAnonymousClass.I() { + public void foo() throws Exception { + boolean var1 = true;// 13 + boolean var2 = true;// 14 + } + };// 11 + var2.foo();// 17 + } else { + System.out.println(5);// 21 + } + + } + + void boo() { + boolean var1 = true;// 35 + } + + void zoo() { + boolean var1 = true;// 39 + } + + private static class Inner { + private static final Runnable R_I = new Runnable() { + public void run() { + boolean var1 = true;// 66 + boolean var2 = true;// 67 + } + }; + } + + interface I { + void foo() throws Exception; + } +} + +class 'pkg/TestAnonymousClass$2' { + method 'run ()V' { + 0 5 + 1 5 + 2 6 + 3 6 + } +} + +class 'pkg/TestAnonymousClass$3' { + method 'run ()V' { + 0 11 + 1 11 + 2 12 + 3 12 + } +} + +class 'pkg/TestAnonymousClass$4' { + method 'run ()V' { + 0 17 + 1 17 + 2 18 + 3 18 + } +} + +class 'pkg/TestAnonymousClass$1' { + method 'foo ()V' { + 0 26 + 1 26 + 2 27 + 3 27 + } +} + +class 'pkg/TestAnonymousClass' { + method 'foo (I)V' { + 1 23 + c 29 + e 30 + 16 32 + 19 32 + 1a 32 + } + + method 'boo ()V' { + 0 38 + 1 38 + } + + method 'zoo ()V' { + 0 42 + 1 42 + } +} + +class 'pkg/TestAnonymousClass$Inner$1' { + method 'run ()V' { + 0 48 + 1 48 + 2 49 + 3 49 + } +} + +Lines mapping: +10 <-> 24 +11 <-> 30 +13 <-> 27 +14 <-> 28 +17 <-> 31 +21 <-> 33 +28 <-> 6 +29 <-> 7 +35 <-> 39 +39 <-> 43 +45 <-> 12 +46 <-> 13 +53 <-> 18 +54 <-> 19 +66 <-> 49 +67 <-> 50 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassCast.dec b/plugins/java-decompiler/engine/testData/results/TestClassCast.dec index e09162ca0f5f..7593d6d01a57 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassCast.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassCast.dec @@ -5,11 +5,30 @@ import java.util.List; public class TestClassCast { public void test(List var1) { - Object var2 = var1; - if(var1 != null) { - ((List)(var2 = new ArrayList(var1))).add("23"); + Object var2 = var1;// 22 + if(var1 != null) {// 23 + ((List)(var2 = new ArrayList(var1))).add("23");// 24 } - System.out.println(((List)var2).size()); + System.out.println(((List)var2).size());// 26 } } + +class 'pkg/TestClassCast' { + method 'test (Ljava/util/List;)V' { + 1 7 + 3 8 + f 9 + 10 9 + 12 9 + 18 12 + 1c 12 + 21 12 + } +} + +Lines mapping: +22 <-> 8 +23 <-> 9 +24 <-> 10 +26 <-> 13 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassFields.dec b/plugins/java-decompiler/engine/testData/results/TestClassFields.dec index 749d828c2a71..1415306b340d 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassFields.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassFields.dec @@ -5,6 +5,17 @@ public class TestClassFields { private static String[] names = new String[]{"name1", "name2"}; static { - sizes = new int[names.length]; + sizes = new int[names.length];// 26 } } + +class 'pkg/TestClassFields' { + method ' ()V' { + 11 7 + 14 7 + 17 7 + } +} + +Lines mapping: +26 <-> 8 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec b/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec index d0485d352461..5dadaf7581f8 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec @@ -13,61 +13,161 @@ public class TestClassLambda { public int field = 0; public void testLambda() { - List var1 = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7)}); - int var2 = (int)Math.random(); - var1.forEach((var2x) -> { + List var1 = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7)});// 27 + int var2 = (int)Math.random();// 28 + var1.forEach((var2x) -> {// 30 int var3 = 2 * var2x.intValue(); System.out.println(var3 + var2 + this.field); }); } public void testLambda1() { - int var1 = (int)Math.random(); + int var1 = (int)Math.random();// 37 Runnable var2 = () -> { System.out.println("hello1" + var1); - }; + };// 38 Runnable var3 = () -> { System.out.println("hello2" + var1); - }; + };// 39 } public void testLambda2() { - reduce((var0, var1) -> { + reduce((var0, var1) -> {// 43 return Math.max(var0, var1); }); } public void testLambda3() { - reduce(Math::max); + reduce(Math::max);// 47 } public void testLambda4() { - reduce(TestClassLambda::localMax); + reduce(TestClassLambda::localMax);// 51 } public void testLambda5() { - String var1 = "abcd"; - function(var1::toString); + String var1 = "abcd";// 55 + function(var1::toString);// 56 } public void testLambda6() { - ArrayList var1 = new ArrayList(); - int var2 = var1.size() * 2; - int var3 = var1.size() * 5; - var1.removeIf((var2x) -> { + ArrayList var1 = new ArrayList();// 60 + int var2 = var1.size() * 2;// 61 + int var3 = var1.size() * 5;// 62 + var1.removeIf((var2x) -> {// 63 return var2 >= var2x.length() && var2x.length() <= var3; }); } public static OptionalInt reduce(IntBinaryOperator var0) { - return null; + return null;// 67 } public static String function(Supplier var0) { - return (String)var0.get(); + return (String)var0.get();// 71 } public static int localMax(int var0, int var1) { - return 0; + return 0;// 75 } } + +class 'pkg/TestClassLambda' { + method 'testLambda ()V' { + 7 15 + 8 15 + e 15 + f 15 + 15 15 + 16 15 + 1c 15 + 1d 15 + 23 15 + 24 15 + 2a 15 + 2c 15 + 33 15 + 35 15 + 39 15 + 3c 15 + 3d 16 + 40 16 + 41 16 + 4a 17 + } + + method 'testLambda1 ()V' { + 0 24 + 3 24 + 4 24 + b 27 + 12 30 + } + + method 'testLambda2 ()V' { + 5 34 + } + + method 'testLambda3 ()V' { + 5 40 + } + + method 'testLambda4 ()V' { + 5 44 + } + + method 'testLambda5 ()V' { + 0 48 + 2 48 + e 49 + } + + method 'testLambda6 ()V' { + 7 53 + 9 54 + e 54 + f 54 + 10 54 + 12 55 + 17 55 + 18 55 + 19 55 + 22 56 + } + + method 'reduce (Ljava/util/function/IntBinaryOperator;)Ljava/util/OptionalInt;' { + 0 62 + 1 62 + } + + method 'function (Ljava/util/function/Supplier;)Ljava/lang/String;' { + 1 66 + 6 66 + 9 66 + } + + method 'localMax (II)I' { + 0 70 + 1 70 + } +} + +Lines mapping: +27 <-> 16 +28 <-> 17 +30 <-> 18 +37 <-> 25 +38 <-> 28 +39 <-> 31 +43 <-> 35 +47 <-> 41 +51 <-> 45 +55 <-> 49 +56 <-> 50 +60 <-> 54 +61 <-> 55 +62 <-> 56 +63 <-> 57 +67 <-> 63 +71 <-> 67 +75 <-> 71 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec b/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec index 74b8bac5d5e7..5384a981e0f3 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec @@ -3,16 +3,16 @@ package pkg; public class TestClassLoop { public static void testSimpleInfinite() { while(true) { - System.out.println(); + System.out.println();// 23 } } public static void testFinally() { - boolean var0 = Math.random() > 0.0D; + boolean var0 = Math.random() > 0.0D;// 29 while(true) { try { - if(!var0) { + if(!var0) {// 33 return; } } finally { @@ -22,16 +22,16 @@ public class TestClassLoop { } public static void testFinallyContinue() { - boolean var0 = Math.random() > 0.0D; + boolean var0 = Math.random() > 0.0D;// 45 while(true) { while(true) { try { - System.out.println("1"); + System.out.println("1");// 49 break; } finally { if(var0) { - System.out.println("3"); + System.out.println("3");// 53 continue; } } @@ -41,3 +41,39 @@ public class TestClassLoop { } } } + +class 'pkg/TestClassLoop' { + method 'testSimpleInfinite ()V' { + 0 5 + 3 5 + } + + method 'testFinally ()V' { + 0 10 + 3 10 + 4 10 + d 10 + f 14 + } + + method 'testFinallyContinue ()V' { + 0 24 + 3 24 + 4 24 + d 24 + e 29 + 11 29 + 13 29 + 2a 33 + 2d 33 + 2f 33 + } +} + +Lines mapping: +23 <-> 6 +29 <-> 11 +33 <-> 15 +45 <-> 25 +49 <-> 30 +53 <-> 34 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec b/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec index 585b01a0261c..b9fa69cdb22e 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec @@ -8,7 +8,27 @@ public class TestClassNestedInitializer { { this.secret = "one"; } - }; - System.out.println(var1.secret); + };// 22 + System.out.println(var1.secret);// 23 } } + +class 'pkg/TestClassNestedInitializer$1' { + method ' (Lpkg/TestClassNestedInitializer;)V' { + a 8 + c 8 + } +} + +class 'pkg/TestClassNestedInitializer' { + method 'test ()V' { + 8 10 + 9 11 + d 11 + 10 11 + } +} + +Lines mapping: +22 <-> 11 +23 <-> 12 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec index e284fa5b7947..291151311a18 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec @@ -2,25 +2,25 @@ package pkg; public class TestClassSimpleBytecodeMapping { public int test() { - System.out.println("before"); - this.run(new Runnable() { + System.out.println("before");// 12 + this.run(new Runnable() {// 14 public void run() { - System.out.println("Runnable"); + System.out.println("Runnable");// 17 } }); - this.test2("1"); - if(Math.random() > 0.0D) { - System.out.println("0"); - return 0; + this.test2("1");// 21 + if(Math.random() > 0.0D) {// 23 + System.out.println("0");// 24 + return 0;// 25 } else { - System.out.println("1"); - return 1; + System.out.println("1");// 27 + return 1;// 28 } } public void test2(String var1) { try { - Integer.parseInt(var1); + Integer.parseInt(var1);// 34 } catch (Exception var6) { System.out.println(var6); } finally { @@ -30,18 +30,18 @@ public class TestClassSimpleBytecodeMapping { } void run(Runnable var1) { - var1.run(); + var1.run();// 49 } public class InnerClass2 { public void print() { - System.out.println("Inner2"); + System.out.println("Inner2");// 54 } } public class InnerClass { public void print() { - System.out.println("Inner"); + System.out.println("Inner");// 44 } } } diff --git a/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec b/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec index 50efbe9b16f9..695350fad6b6 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec @@ -2,13 +2,32 @@ package pkg; public class TestClassSwitch { public void testCaseOrder(int var1) { - switch(var1) { + switch(var1) {// 22 case 5: - System.out.println(5); + System.out.println(5);// 27 default: - return; + return;// 29 case 13: - System.out.println(13); + System.out.println(13);// 24 } } } + +class 'pkg/TestClassSwitch' { + method 'testCaseOrder (I)V' { + 1 4 + 1c 10 + 1f 10 + 21 10 + 25 6 + 28 6 + 29 6 + 2c 8 + } +} + +Lines mapping: +22 <-> 5 +24 <-> 11 +27 <-> 7 +29 <-> 9 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec b/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec index 7a50473fc3e7..f2a3fdbbfbea 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec @@ -5,45 +5,122 @@ import java.util.List; public class TestClassTypes { public void testBoolean() { - byte var1 = 0; - long var2 = System.currentTimeMillis(); - if(var2 % 2L > 0L) { - var1 = 1; - } else if(var2 % 3L > 0L) { - var1 = 2; + byte var1 = 0;// 25 + long var2 = System.currentTimeMillis();// 26 + if(var2 % 2L > 0L) {// 28 + var1 = 1;// 29 + } else if(var2 % 3L > 0L) {// 31 + var1 = 2;// 32 } - if(var1 == 1) { - System.out.println(); + if(var1 == 1) {// 35 + System.out.println();// 36 } } public boolean testBit(int var1) { - return (var1 & 1) == 1; + return (var1 & 1) == 1;// 41 } public void testSwitchConsts(int var1) { - switch(var1) { + switch(var1) {// 46 case 88: - System.out.println("1"); + System.out.println("1");// 48 break; case 656: - System.out.println("2"); + System.out.println("2");// 51 break; case 65201: case 65489: - System.out.println("3"); + System.out.println("3");// 55 } } public void testAssignmentType(List var1) { - Object var2 = var1; - if(var1 != null) { - ((List)(var2 = new ArrayList(var1))).add("23"); + Object var2 = var1;// 61 + if(var1 != null) {// 63 + ((List)(var2 = new ArrayList(var1))).add("23");// 64 } - System.out.println(((List)var2).size()); + System.out.println(((List)var2).size());// 67 } } + +class 'pkg/TestClassTypes' { + method 'testBoolean ()V' { + 0 7 + 1 7 + 2 8 + 5 8 + 7 9 + a 9 + b 9 + c 9 + d 9 + 10 10 + 11 10 + 16 11 + 19 11 + 1a 11 + 1b 11 + 1c 11 + 1f 12 + 20 12 + 22 15 + 23 15 + 26 16 + 29 16 + } + + method 'testBit (I)Z' { + 1 22 + 2 22 + 3 22 + c 22 + } + + method 'testSwitchConsts (I)V' { + 1 26 + 2c 28 + 2f 28 + 31 28 + 37 31 + 3a 31 + 3c 31 + 42 35 + 45 35 + 47 35 + } + + method 'testAssignmentType (Ljava/util/List;)V' { + 1 41 + 3 42 + f 43 + 10 43 + 12 43 + 18 46 + 1c 46 + 21 46 + } +} + +Lines mapping: +25 <-> 8 +26 <-> 9 +28 <-> 10 +29 <-> 11 +31 <-> 12 +32 <-> 13 +35 <-> 16 +36 <-> 17 +41 <-> 23 +46 <-> 27 +48 <-> 29 +51 <-> 32 +55 <-> 36 +61 <-> 42 +63 <-> 43 +64 <-> 44 +67 <-> 47 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassVar.dec b/plugins/java-decompiler/engine/testData/results/TestClassVar.dec index 4cfd27f7854d..14d2e070393d 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassVar.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassVar.dec @@ -5,12 +5,12 @@ public class TestClassVar { public int field_int = 0; public void testFieldSSAU() { - for(int var1 = 0; var1 < 10; ++var1) { + for(int var1 = 0; var1 < 10; ++var1) {// 26 try { - System.out.println(); + System.out.println();// 29 } finally { if(this.field_boolean) { - System.out.println(); + System.out.println();// 33 } } @@ -19,22 +19,65 @@ public class TestClassVar { } public Long testFieldSSAU1() { - return new Long((long)(this.field_int++)); + return new Long((long)(this.field_int++));// 40 } public void testComplexPropagation() { - int var1 = 0; + int var1 = 0;// 45 - while(var1 < 10) { + while(var1 < 10) {// 47 int var2; - for(var2 = var1; var1 < 10 && var1 == 0; ++var1) { + for(var2 = var1; var1 < 10 && var1 == 0; ++var1) {// 49 ; } - if(var2 != var1) { - System.out.println(); + if(var2 != var1) {// 54 + System.out.println();// 55 } } } } + +class 'pkg/TestClassVar' { + method 'testFieldSSAU ()V' { + 0 7 + 1 7 + 3 7 + 8 9 + b 9 + 26 12 + 29 12 + } + + method 'testFieldSSAU1 ()Ljava/lang/Long;' { + 6 21 + b 21 + f 21 + 13 21 + } + + method 'testComplexPropagation ()V' { + 0 25 + 1 25 + 3 27 + 9 29 + b 29 + 14 29 + 1c 33 + 1f 34 + 22 34 + } +} + +Lines mapping: +26 <-> 8 +29 <-> 10 +33 <-> 13 +40 <-> 22 +45 <-> 26 +47 <-> 28 +49 <-> 30 +51 <-> 30 +54 <-> 34 +55 <-> 35 diff --git a/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec b/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec index eb9de8daa07a..eeb9c19a91e2 100644 --- a/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec +++ b/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec @@ -4,10 +4,26 @@ class TestCodeConstructs { private int count = 0; void expressions() { - (new String()).hashCode(); + (new String()).hashCode();// 20 } Integer fieldIncrement() { - return new Integer(this.count++); + return new Integer(this.count++);// 25 } } + +class 'pkg/TestCodeConstructs' { + method 'expressions ()V' { + 7 6 + } + + method 'fieldIncrement ()Ljava/lang/Integer;' { + 6 10 + b 10 + 12 10 + } +} + +Lines mapping: +20 <-> 7 +25 <-> 11 diff --git a/plugins/java-decompiler/engine/testData/results/TestConstants.dec b/plugins/java-decompiler/engine/testData/results/TestConstants.dec index 216da8e98468..47f4c1d3a72b 100644 --- a/plugins/java-decompiler/engine/testData/results/TestConstants.dec +++ b/plugins/java-decompiler/engine/testData/results/TestConstants.dec @@ -71,3 +71,4 @@ public class TestConstants { Class value(); } } + diff --git a/plugins/java-decompiler/engine/testData/results/TestDebugSymbols.dec b/plugins/java-decompiler/engine/testData/results/TestDebugSymbols.dec index 42ae7a8c5513..e96eb3328706 100644 --- a/plugins/java-decompiler/engine/testData/results/TestDebugSymbols.dec +++ b/plugins/java-decompiler/engine/testData/results/TestDebugSymbols.dec @@ -2,10 +2,40 @@ package pkg; class TestDebugSymbols { private int m() { - String text = "text"; - long prolonged = 42L; - float decimated = (float)prolonged / 10.0F; - double doubled = (double)(2.0F * decimated); - return (text + ":" + prolonged + ":" + decimated + ":" + doubled).length(); + String text = "text";// 21 + long prolonged = 42L;// 22 + float decimated = (float)prolonged / 10.0F;// 23 + double doubled = (double)(2.0F * decimated);// 24 + return (text + ":" + prolonged + ":" + decimated + ":" + doubled).length();// 25 } } + +class 'pkg/TestDebugSymbols' { + method 'm ()I' { + 0 4 + 2 4 + 3 5 + 6 5 + 8 6 + 9 6 + b 6 + c 6 + e 7 + 11 7 + 12 7 + 13 7 + 20 8 + 29 8 + 33 8 + 3d 8 + 40 8 + 43 8 + } +} + +Lines mapping: +21 <-> 5 +22 <-> 6 +23 <-> 7 +24 <-> 8 +25 <-> 9 diff --git a/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec b/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec index 237ac9c72348..e423854d729a 100644 --- a/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec +++ b/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec @@ -1,6 +1,6 @@ package pkg; -public class TestDeprecations { +public abstract class TestDeprecations { /** @deprecated */ public int byComment; /** @deprecated */ @@ -9,19 +9,70 @@ public class TestDeprecations { /** @deprecated */ public void byComment() { + boolean var1 = true;// 27 } + /** @deprecated */ + public abstract void byCommentAbstract(); + /** @deprecated */ @Deprecated public void byAnno() { + boolean var1 = true;// 35 } + /** @deprecated */ + @Deprecated + public abstract void byAnnoAbstract(); + /** @deprecated */ @Deprecated public static class ByAnno { + int a = 5; + + void foo() { + boolean var1 = true;// 55 + } } /** @deprecated */ public static class ByComment { + int a = 5; + + void foo() { + boolean var1 = true;// 46 + } } } + +class 'pkg/TestDeprecations' { + method 'byComment ()V' { + 0 11 + 1 11 + } + + method 'byAnno ()V' { + 0 20 + 1 20 + } +} + +class 'pkg/TestDeprecations$ByAnno' { + method 'foo ()V' { + 0 33 + 1 33 + } +} + +class 'pkg/TestDeprecations$ByComment' { + method 'foo ()V' { + 0 42 + 1 42 + } +} + +Lines mapping: +27 <-> 12 +35 <-> 21 +46 <-> 43 +55 <-> 34 diff --git a/plugins/java-decompiler/engine/testData/results/TestEnum.dec b/plugins/java-decompiler/engine/testData/results/TestEnum.dec index 3184741d4043..e08f341a6065 100644 --- a/plugins/java-decompiler/engine/testData/results/TestEnum.dec +++ b/plugins/java-decompiler/engine/testData/results/TestEnum.dec @@ -18,10 +18,25 @@ public enum TestEnum { } private TestEnum() { - this("?"); + this("?");// 34 } private TestEnum(@Deprecated String var3) { - this.s = var3; + this.s = var3;// 35 } } + +class 'pkg/TestEnum' { + method ' (Ljava/lang/String;I)V' { + 3 20 + 5 20 + } + + method ' (Ljava/lang/String;ILjava/lang/String;)V' { + 8 24 + } +} + +Lines mapping: +34 <-> 21 +35 <-> 25 diff --git a/plugins/java-decompiler/engine/testData/results/TestExtendsList.dec b/plugins/java-decompiler/engine/testData/results/TestExtendsList.dec index b4aacf6e126a..6f116dbad41c 100644 --- a/plugins/java-decompiler/engine/testData/results/TestExtendsList.dec +++ b/plugins/java-decompiler/engine/testData/results/TestExtendsList.dec @@ -2,10 +2,26 @@ package pkg; public class TestExtendsList { static > T m1(T var0) { - return null; + return null;// 20 } static > T m2(T var0) { - return null; + return null;// 24 } } + +class 'pkg/TestExtendsList' { + method 'm1 (Ljava/lang/Comparable;)Ljava/lang/Comparable;' { + 0 4 + 1 4 + } + + method 'm2 (Ljava/lang/Object;)Ljava/lang/Object;' { + 0 8 + 1 8 + } +} + +Lines mapping: +20 <-> 5 +24 <-> 9 diff --git a/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec b/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec index 9b63154af169..3db62038d2f6 100644 --- a/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec +++ b/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec @@ -2,16 +2,40 @@ package pkg; class TestInnerClassConstructor { void m() { - new TestInnerClassConstructor.Inner("text"); + new TestInnerClassConstructor.Inner("text");// 5 } void n(String var1) { - System.out.println("n(): " + var1); + System.out.println("n(): " + var1);// 9 } final class Inner { private Inner(String var2) { - TestInnerClassConstructor.this.n(var2); + TestInnerClassConstructor.this.n(var2);// 14 } } } + +class 'pkg/TestInnerClassConstructor' { + method 'm ()V' { + 5 4 + } + + method 'n (Ljava/lang/String;)V' { + 0 8 + a 8 + 13 8 + 16 8 + } +} + +class 'pkg/TestInnerClassConstructor$Inner' { + method ' (Lpkg/TestInnerClassConstructor;Ljava/lang/String;)V' { + b 13 + } +} + +Lines mapping: +5 <-> 5 +9 <-> 9 +14 <-> 14 diff --git a/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec b/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec new file mode 100644 index 000000000000..8e511673bb18 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec @@ -0,0 +1,61 @@ +package pkg; + +public abstract class TestLocalClass { + void foo() { + boolean var1 = true;// 8 + class Local { + void foo() { + boolean var1 = true;// 11 + boolean var2 = true;// 12 + } + } + + Local var2 = new Local();// 15 + var2.foo();// 16 + } + + void boo() { + boolean var1 = true;// 20 + } + + void zoo() { + boolean var1 = true;// 24 + } +} + +class 'pkg/TestLocalClass$1Local' { + method 'foo ()V' { + 0 7 + 1 7 + 2 8 + 3 8 + } +} + +class 'pkg/TestLocalClass' { + method 'foo ()V' { + 0 4 + 1 4 + a 12 + c 13 + } + + method 'boo ()V' { + 0 17 + 1 17 + } + + method 'zoo ()V' { + 0 21 + 1 21 + } +} + +Lines mapping: +8 <-> 5 +11 <-> 8 +12 <-> 9 +15 <-> 13 +16 <-> 14 +20 <-> 18 +24 <-> 22 diff --git a/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec b/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec index e4c4724d7a7c..a45819211428 100644 --- a/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec +++ b/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec @@ -40,3 +40,4 @@ public class TestMethodParameters { } } } + diff --git a/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec b/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec index fa411a643acd..ca38d8c0e732 100644 --- a/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec @@ -2,13 +2,13 @@ package pkg; public class TestSynchronizedMapping { public int test(int var1) { - synchronized(this) { - return var1++; + synchronized(this) {// 8 + return var1++;// 9 } } public void test2(String var1) { - System.out.println(var1); + System.out.println(var1);// 14 } } diff --git a/plugins/java-decompiler/engine/testData/results/TestThrowException.dec b/plugins/java-decompiler/engine/testData/results/TestThrowException.dec new file mode 100644 index 000000000000..7bc460e5f519 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestThrowException.dec @@ -0,0 +1,39 @@ +package pkg; + +public class TestThrowException { + Runnable r; + + public TestThrowException(int var1) { + if(var1 > 0) {// 9 + throw new IllegalArgumentException("xxx");// 10 + } else { + this.r = new Runnable() {// 12 + public void run() { + boolean var1 = true;// 15 + } + }; + } + } +} + +class 'pkg/TestThrowException$1' { + method 'run ()V' { + 0 11 + 1 11 + } +} + +class 'pkg/TestThrowException' { + method ' (I)V' { + 5 6 + c 7 + 11 7 + 1b 9 + } +} + +Lines mapping: +9 <-> 7 +10 <-> 8 +12 <-> 10 +15 <-> 12 diff --git a/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec b/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec index 9840bfccb285..673238ec14fb 100644 --- a/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec +++ b/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec @@ -3,10 +3,10 @@ package pkg; public class TestTryCatchFinally { public void test1(String var1) { try { - System.out.println("sout1"); + System.out.println("sout1");// 24 } catch (Exception var9) { try { - System.out.println("sout2"); + System.out.println("sout2");// 27 } catch (Exception var8) { ; } @@ -16,9 +16,19 @@ public class TestTryCatchFinally { } + int foo(int var1) throws Exception { + if(var1 < 1) {// 39 + throw new RuntimeException();// 40 + } else if(var1 < 5) {// 41 + return var1;// 42 + } else { + throw new Exception();// 45 + } + } + public int test(String var1) { try { - int var2 = Integer.parseInt(var1); + int var2 = Integer.parseInt(var1);// 51 return var2; } catch (Exception var6) { System.out.println("Error" + var6); @@ -29,3 +39,39 @@ public class TestTryCatchFinally { return -1; } } + +class 'pkg/TestTryCatchFinally' { + method 'test1 (Ljava/lang/String;)V' { + 0 5 + 3 5 + 5 5 + 14 8 + 17 8 + 19 8 + } + + method 'foo (I)I' { + 1 19 + 2 19 + c 20 + e 21 + f 21 + 13 22 + 1b 24 + } + + method 'test (Ljava/lang/String;)I' { + 1 30 + 4 30 + } +} + +Lines mapping: +24 <-> 6 +27 <-> 9 +39 <-> 20 +40 <-> 21 +41 <-> 22 +42 <-> 23 +45 <-> 25 +51 <-> 31 diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestAbstractMethods.java b/plugins/java-decompiler/engine/testData/src/pkg/TestAbstractMethods.java new file mode 100644 index 000000000000..9a05f11b93e4 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestAbstractMethods.java @@ -0,0 +1,19 @@ +package pkg; + +import java.lang.Override; +import java.lang.Runnable; + +public abstract class TestAbstractMethods { + + public abstract void foo(); + + public int test(int a) { + return a; + } + + protected abstract void foo1(); + + public void test2(String a) { + System.out.println(a); + } +} diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestAnonymousClass.java b/plugins/java-decompiler/engine/testData/src/pkg/TestAnonymousClass.java new file mode 100644 index 000000000000..3c2e3b006266 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestAnonymousClass.java @@ -0,0 +1,71 @@ +package pkg; + +import java.lang.Exception; +import java.lang.Override; +import java.lang.Runnable; + +public abstract class TestAnonymousClass { + void foo(int i) + throws Exception { + if (i > 0) { + I r = new I() { + public void foo() throws Exception { + int a = 5; + int b = 5; + } + }; + r.foo(); + } + else { + final int x =5; + System.out.println(x); + } + } + + public static final Runnable R3 = new Runnable() { + @Override + public void run() { + int a =5; + int b =5; + } + }; + + + void boo() { + int a =5; + } + + void zoo() { + int a =5; + } + + public static final Runnable R = new Runnable() { + @Override + public void run() { + int a =5; + int b =5; + } + }; + + public static final Runnable R1 = new Runnable() { + @Override + public void run() { + int a =5; + int b =5; + } + }; + + interface I { + void foo() throws Exception; + } + + private static class Inner { + private static Runnable R_I = new Runnable() { + @Override + public void run() { + int a =5; + int b =5; + } + }; + } +} diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestDeprecations.java b/plugins/java-decompiler/engine/testData/src/pkg/TestDeprecations.java index 18ba0b5f10a6..0f6baad7d9fd 100644 --- a/plugins/java-decompiler/engine/testData/src/pkg/TestDeprecations.java +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestDeprecations.java @@ -15,7 +15,7 @@ */ package pkg; -public class TestDeprecations { +public abstract class TestDeprecations { /** @deprecated */ public int byComment; @@ -23,14 +23,36 @@ public class TestDeprecations { public int byAnno; /** @deprecated */ - public void byComment() { } - - @Deprecated - public void byAnno() { } + public void byComment() { + int a =5; + } /** @deprecated */ - public static class ByComment { } + public abstract void byCommentAbstract(); @Deprecated - public static class ByAnno { } + public void byAnno() { + int a =5; + } + + @Deprecated + public abstract void byAnnoAbstract(); + + /** @deprecated */ + public static class ByComment { + int a =5; + + void foo() { + int x = 5; + } + } + + @Deprecated + public static class ByAnno { + int a =5; + + void foo() { + int x = 5; + } + } } \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestLocalClass.java b/plugins/java-decompiler/engine/testData/src/pkg/TestLocalClass.java new file mode 100644 index 000000000000..3667a9408ca3 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestLocalClass.java @@ -0,0 +1,26 @@ +package pkg; + +import java.lang.Override; +import java.lang.Runnable; + +public abstract class TestLocalClass { + void foo() { + int a =5; + class Local{ + void foo() { + int b = 5; + int v = 5; + } + }; + Local l = new Local(); + l.foo(); + } + + void boo() { + int a =5; + } + + void zoo() { + int a =5; + } +} diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestThrowException.java b/plugins/java-decompiler/engine/testData/src/pkg/TestThrowException.java new file mode 100644 index 000000000000..76d571a2c78d --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestThrowException.java @@ -0,0 +1,19 @@ +package pkg; + +import java.lang.Override; +import java.lang.Runnable; + +public class TestThrowException { + Runnable r; + public TestThrowException(int a) { + if (a > 0) { + throw new IllegalArgumentException("xxx"); + } + r = new Runnable() { + @Override + public void run() { + int a = 5; + } + }; + } +} diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestTryCatchFinally.java b/plugins/java-decompiler/engine/testData/src/pkg/TestTryCatchFinally.java index da3588a3eb50..2c4980000480 100644 --- a/plugins/java-decompiler/engine/testData/src/pkg/TestTryCatchFinally.java +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestTryCatchFinally.java @@ -15,6 +15,9 @@ */ package pkg; +import java.lang.Exception; +import java.lang.RuntimeException; + public class TestTryCatchFinally { public void test1(String x) { try { @@ -32,6 +35,17 @@ public class TestTryCatchFinally { } } + int foo(int a) throws Exception { + if (a < 1) { + throw new RuntimeException(); + } else if ( a <5) { + return a; + } + else { + throw new Exception(); + } + } + public int test(String a) { try { return Integer.parseInt(a); diff --git a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java index b04e42f80640..f2ed7234414e 100644 --- a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java +++ b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java @@ -65,9 +65,11 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { } public void testStubCompatibility() { + Registry.get("decompiler.dump.original.lines").setValue(true); String path = PlatformTestUtil.getRtJarPath() + "!/java"; VirtualFile dir = getTestFile(path); doTestStubCompatibility(dir); + Registry.get("decompiler.dump.original.lines").setValue(false); } private void doTestStubCompatibility(VirtualFile root) { @@ -83,6 +85,15 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { PsiElement mirror = ((ClsFileImpl)clsFile).getMirror(); String decompiled = mirror.getText(); assertTrue(file.getPath(), decompiled.contains(file.getNameWithoutExtension())); + + // check that no mapped line number is on an empty line + String prefix = "// "; + for (String s : decompiled.split("\n")) { + int pos = s.indexOf(prefix); + if (pos == 0 && prefix.length() < s.length() && Character.isDigit(s.charAt(prefix.length()))) { + fail("Incorrect line mapping in file " + file.getPath() + " line: " + s); + } + } } return true; } diff --git a/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java b/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java index cc00d6666f17..9f7daa1deade 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java +++ b/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java @@ -20,12 +20,14 @@ import com.intellij.execution.Location; import com.intellij.execution.junit2.events.*; import com.intellij.execution.junit2.info.MethodLocation; import com.intellij.execution.junit2.info.TestInfo; +import com.intellij.execution.junit2.states.ComparisonFailureState; import com.intellij.execution.junit2.states.IgnoredState; import com.intellij.execution.junit2.states.Statistics; import com.intellij.execution.junit2.states.TestState; import com.intellij.execution.testframework.AbstractTestProxy; import com.intellij.execution.testframework.Filter; import com.intellij.execution.testframework.TestConsoleProperties; +import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.pom.Navigatable; @@ -325,14 +327,14 @@ public class TestProxy extends AbstractTestProxy { @Override @Nullable - public AssertEqualsDiffViewerProvider getDiffViewerProvider() { - if (myState instanceof AssertEqualsDiffViewerProvider) { - return (AssertEqualsDiffViewerProvider)myState; + public DiffHyperlink getDiffViewerProvider() { + if (myState instanceof ComparisonFailureState) { + return ((ComparisonFailureState)myState).getHyperlink(); } for (TestProxy proxy : getChildren()) { if (!proxy.isDefect()) continue; - final AssertEqualsDiffViewerProvider provider = proxy.getDiffViewerProvider(); + final DiffHyperlink provider = proxy.getDiffViewerProvider(); if (provider != null) { return provider; } diff --git a/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java b/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java index c772936f5d20..8a036c7fa04a 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java +++ b/plugins/junit/src/com/intellij/execution/junit2/states/ComparisonFailureState.java @@ -17,14 +17,12 @@ package com.intellij.execution.junit2.states; import com.intellij.execution.junit2.segments.ObjectReader; -import com.intellij.execution.testframework.AbstractTestProxy; import com.intellij.execution.testframework.Printer; import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.execution.ui.ConsoleViewContentType; -import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NonNls; -public class ComparisonFailureState extends FaultyState implements AbstractTestProxy.AssertEqualsMultiDiffViewProvider { +public class ComparisonFailureState extends FaultyState { private DiffHyperlink myHyperlink; @NonNls protected static final String EXPECTED_VALUE_MESSAGE_TEXT = "expected:<"; @@ -48,30 +46,7 @@ public class ComparisonFailureState extends FaultyState implements AbstractTestP myHyperlink.printOn(printer); } - public String getExpected() { - return myHyperlink.getLeft(); - } - - public String getActual() { - return myHyperlink.getRight(); - } - - public void openDiff(final Project project) { - if (myHyperlink != null) myHyperlink.openDiff(project); - } - - @Override - public void openMultiDiff(Project project, AbstractTestProxy.AssertEqualsDiffChain chain) { - if (myHyperlink != null) { - myHyperlink.openMultiDiff(project, chain); - } - } - - @Override - public String getFilePath() { - if (myHyperlink != null) { - return myHyperlink.getFilePath(); - } - return null; + public DiffHyperlink getHyperlink() { + return myHyperlink; } } diff --git a/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java b/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java index 10041448d97c..5ccff9f9b249 100644 --- a/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java +++ b/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java @@ -24,16 +24,23 @@ import com.intellij.lang.properties.editor.ResourceBundleAsVirtualFile; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.Nullable; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.*; /** * @author Dmitry Batkovich */ public class DissociateResourceBundleAction extends AnAction { - private static final String PRESENTATION_TEXT_TEMPLATE = "Dissociate Resource Bundle '%s'"; + private static final String SINGLE_RB_PRESENTATION_TEXT_TEMPLATE = "Dissociate Resource Bundle '%s'"; + private static final String MULTIPLE_RB_PRESENTATION_TEXT_TEMPLATE = "Dissociate %s Resource Bundles"; public DissociateResourceBundleAction() { super(null, null, AllIcons.FileTypes.Properties); @@ -41,40 +48,62 @@ public class DissociateResourceBundleAction extends AnAction { @Override public void actionPerformed(final AnActionEvent e) { - final ResourceBundle resourceBundle = extractResourceBundle(e); - assert resourceBundle != null; - final Project project = resourceBundle.getProject(); + final Project project = e.getProject(); + if (project == null) { + return; + } + final Collection resourceBundles = extractResourceBundles(e); + assert resourceBundles.size() > 0; final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); - fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); - for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { - fileEditorManager.closeFile(propertiesFile.getVirtualFile()); + for (ResourceBundle resourceBundle : resourceBundles) { + fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); + for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { + fileEditorManager.closeFile(propertiesFile.getVirtualFile()); + } + ResourceBundleManager.getInstance(e.getProject()).dissociateResourceBundle(resourceBundle); } - ResourceBundleManager.getInstance(e.getProject()).dissociateResourceBundle(resourceBundle); ProjectView.getInstance(project).refresh(); } @Override public void update(final AnActionEvent e) { - final ResourceBundle resourceBundle = extractResourceBundle(e); - if (resourceBundle != null) { - e.getPresentation().setText(String.format(PRESENTATION_TEXT_TEMPLATE, resourceBundle.getBaseName()), false); + final Collection resourceBundles = extractResourceBundles(e); + if (!resourceBundles.isEmpty()) { + final String actionText = resourceBundles.size() == 1 ? + String.format(SINGLE_RB_PRESENTATION_TEXT_TEMPLATE, ContainerUtil.getFirstItem(resourceBundles).getBaseName()) : + String.format(MULTIPLE_RB_PRESENTATION_TEXT_TEMPLATE, resourceBundles.size()); + e.getPresentation().setText(actionText, false); e.getPresentation().setVisible(true); } else { e.getPresentation().setVisible(false); } } - @Nullable - private static ResourceBundle extractResourceBundle(final AnActionEvent event) { - final ResourceBundle[] data = event.getData(ResourceBundle.ARRAY_DATA_KEY); - if (data != null && data.length == 1 && data[0].getPropertiesFiles().size() > 1) { - return data[0]; + @NotNull + private static Collection extractResourceBundles(final AnActionEvent event) { + final Set targetResourceBundles = new HashSet(); + final ResourceBundle[] chosenResourceBundles = event.getData(ResourceBundle.ARRAY_DATA_KEY); + if (chosenResourceBundles != null) { + for (ResourceBundle resourceBundle : chosenResourceBundles) { + if (resourceBundle.getPropertiesFiles().size() > 1) { + targetResourceBundles.add(resourceBundle); + } + } } - final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(event.getData(PlatformDataKeys.PSI_FILE)); - if (propertiesFile == null) { - return null; + final PsiElement[] psiElements = event.getData(LangDataKeys.PSI_ELEMENT_ARRAY); + if (psiElements != null) { + for (PsiElement element : psiElements) { + if (element instanceof PsiFile) { + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile((PsiFile)element); + if (propertiesFile != null) { + final ResourceBundle bundle = propertiesFile.getResourceBundle(); + if (bundle.getPropertiesFiles().size() > 1) { + targetResourceBundles.add(bundle); + } + } + } + } } - final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); - return resourceBundle.getPropertiesFiles().size() > 1 ? resourceBundle : null; + return targetResourceBundles; } } diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java index b91a878024b2..85d9fd90c102 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java @@ -57,7 +57,6 @@ public class PropertiesProjectViewTest extends LightPlatformCodeInsightFixtureTe " xxx_en.properties\n" + " xxx_ru_RU.properties\n" + " X.txt\n" + - myStructure.getProjectFileRepresentation() + " External Libraries\n"; PlatformTestUtil.assertTreeEqual(pane.getTree(), structure); } @@ -74,7 +73,6 @@ public class PropertiesProjectViewTest extends LightPlatformCodeInsightFixtureTe " xxx2.properties\n" + " yyy.properties\n" + " X.txt\n" + - myStructure.getProjectFileRepresentation() + " External Libraries\n"; PlatformTestUtil.assertTreeEqual(pane.getTree(), structure); @@ -94,7 +92,6 @@ public class PropertiesProjectViewTest extends LightPlatformCodeInsightFixtureTe " xxx.properties\n" + " xxx_en.properties\n" + " X.txt\n" + - myStructure.getProjectFileRepresentation() + " External Libraries\n"; PlatformTestUtil.assertTreeEqual(pane.getTree(), structure); @@ -111,7 +108,6 @@ public class PropertiesProjectViewTest extends LightPlatformCodeInsightFixtureTe " xxx_en.properties\n" + " xxx2.properties\n" + " yyy.properties\n" + - myStructure.getProjectFileRepresentation() + " External Libraries\n"; PlatformTestUtil.assertTreeEqual(pane.getTree(), structure); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java index 9fe08a35c09f..89d3e3d7d8f2 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java @@ -376,7 +376,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { @Nullable @Override public CancellableConnection createCancellableConnection() { - return new HttpTestConnection(new HttpGet(getRestApiUrl("me", "cards") + "?limit=1")); + return new HttpTestConnection(new HttpGet(getRestApiUrl("members", "me", "cards") + "?limit=1")); } /** diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java index 07dd0f86e4c9..654b51261d88 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java @@ -156,6 +156,15 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase objects, @NotNull String... names) { assertEquals(message, ContainerUtil.newHashSet(names), ContainerUtil.map2Set(objects, new Function() { @Override diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalStarter.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalStarter.java index 505b31648664..f220b1b11ac0 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalStarter.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalStarter.java @@ -1,7 +1,6 @@ package org.jetbrains.plugins.terminal; import com.intellij.ide.GeneralSettings; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.vfs.LocalFileSystem; import com.jediterm.terminal.*; import com.jediterm.terminal.emulator.JediEmulator; @@ -34,17 +33,7 @@ public class JBTerminalStarter extends TerminalStarter { public static void refreshAfterExecution() { if (GeneralSettings.getInstance().isSyncOnFrameActivation()) { //we need to refresh local file system after a command has been executed in the terminal - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - LocalFileSystem.getInstance().refresh(false); - } - }); - } - }); + LocalFileSystem.getInstance().refresh(true); } } } diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java index 1a0f507436ab..82d7fc77aee8 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java @@ -28,6 +28,8 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.testng.remote.strprotocol.MessageHelper; @@ -290,18 +292,18 @@ public class TestProxy extends AbstractTestProxy { } @Override - public AssertEqualsDiffViewerProvider getDiffViewerProvider() { + public DiffHyperlink getDiffViewerProvider() { if (myHyperlink == null) { for (TestProxy proxy : getChildren()) { if (!proxy.isDefect()) continue; - final AssertEqualsDiffViewerProvider provider = proxy.getDiffViewerProvider(); + final DiffHyperlink provider = proxy.getDiffViewerProvider(); if (provider != null) { return provider; } } return null; } - return new MyAssertEqualsMultiDiffViewProvider(myHyperlink); + return myHyperlink; } private static String trimStackTrace(String stackTrace) { @@ -429,37 +431,4 @@ public class TestProxy extends AbstractTestProxy { return text; } } - - private static class MyAssertEqualsMultiDiffViewProvider implements AssertEqualsMultiDiffViewProvider { - private DiffHyperlink myHyperlink; - - public MyAssertEqualsMultiDiffViewProvider(DiffHyperlink hyperlink) { - myHyperlink = hyperlink; - } - - @Override - public void openDiff(Project project) { - myHyperlink.openDiff(project); - } - - @Override - public String getExpected() { - return myHyperlink.getLeft(); - } - - @Override - public String getActual() { - return myHyperlink.getRight(); - } - - @Override - public void openMultiDiff(Project project, AssertEqualsDiffChain chain) { - myHyperlink.openMultiDiff(project, chain); - } - - @Override - public String getFilePath() { - return myHyperlink.getFilePath(); - } - } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditorProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditorProvider.java index 1e043a3be4af..73f40c0aa8b2 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditorProvider.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditorProvider.java @@ -22,7 +22,6 @@ import com.intellij.openapi.fileEditor.FileEditorProvider; import com.intellij.openapi.fileEditor.FileEditorState; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.ModuleUtil; -import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; @@ -31,7 +30,7 @@ import com.intellij.util.ArrayUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -public final class UIFormEditorProvider implements FileEditorProvider, DumbAware { +public final class UIFormEditorProvider implements FileEditorProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.editor.UIFormEditorProvider"); public boolean accept(@NotNull final Project project, @NotNull final VirtualFile file){ diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 85889184ab09..59e240f8be06 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -170,7 +170,7 @@ public layoutEducational(String classesPath, Set usedJars) { def appInfo = appInfoFile() if (!dryRun) { - wireBuildDate(buildNumber, appInfo) + wireBuildDate("PE-${buildNumber}", appInfo) } Map args = [ diff --git a/python/psi-api/src/com/jetbrains/python/PyNames.java b/python/psi-api/src/com/jetbrains/python/PyNames.java index 21e5be632d59..20a37449454e 100644 --- a/python/psi-api/src/com/jetbrains/python/PyNames.java +++ b/python/psi-api/src/com/jetbrains/python/PyNames.java @@ -503,4 +503,6 @@ public class PyNames { public static final ImmutableSet METHOD_SPECIAL_ATTRIBUTES = ImmutableSet.of("__func__", "__self__"); public static final ImmutableSet LEGACY_METHOD_SPECIAL_ATTRIBUTES = ImmutableSet.of("im_func", "im_self", "im_class"); + + public static final String MRO = "mro"; } diff --git a/python/src/com/jetbrains/python/PyDirectoryIconProvider.java b/python/src/com/jetbrains/python/PyDirectoryIconProvider.java index 6375d7bfc13f..7a24ee7ea7f5 100644 --- a/python/src/com/jetbrains/python/PyDirectoryIconProvider.java +++ b/python/src/com/jetbrains/python/PyDirectoryIconProvider.java @@ -18,6 +18,7 @@ package com.jetbrains.python; import com.intellij.ide.IconProvider; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -26,6 +27,7 @@ import com.jetbrains.python.psi.PyUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.util.Collection; /** * @author yole @@ -35,7 +37,8 @@ public class PyDirectoryIconProvider extends IconProvider { public Icon getIcon(@NotNull PsiElement element, int flags) { if (element instanceof PsiDirectory) { final PsiDirectory directory = (PsiDirectory)element; - if (PyUtil.isPackage(directory, null) && !isSpecialDirectory(directory)) { + // Preserve original icons for excluded directories and source roots + if (!isSpecialDirectory(directory) && isImportablePackage(directory)) { return PlatformIcons.PACKAGE_ICON; } } @@ -43,9 +46,24 @@ public class PyDirectoryIconProvider extends IconProvider { } private static boolean isSpecialDirectory(@NotNull PsiDirectory directory) { - final Module module = ModuleUtilCore.findModuleForPsiElement(directory); final VirtualFile vFile = directory.getVirtualFile(); - // If module is null, directory is probably excluded + if (FileIndexFacade.getInstance(directory.getProject()).isExcludedFile(vFile)) { + return true; + } + final Module module = ModuleUtilCore.findModuleForPsiElement(directory); return module == null || PyUtil.getSourceRoots(module).contains(vFile); } + + private static boolean isImportablePackage(@NotNull PsiDirectory directory) { + final Collection sourceRoots = PyUtil.getSourceRoots(directory); + for (PsiDirectory dir = directory; dir != null; dir = dir.getParentDirectory()) { + if (sourceRoots.contains(dir.getVirtualFile())) { + return true; + } + if (!PyNames.isIdentifier(dir.getName()) || !PyUtil.isPackage(dir, false, null)) { + return false; + } + } + return false; + } } diff --git a/python/src/com/jetbrains/python/buildout/BuildoutFacet.java b/python/src/com/jetbrains/python/buildout/BuildoutFacet.java index 0ba5e7924f3f..ab5c711a48c4 100644 --- a/python/src/com/jetbrains/python/buildout/BuildoutFacet.java +++ b/python/src/com/jetbrains/python/buildout/BuildoutFacet.java @@ -24,6 +24,9 @@ import com.intellij.facet.FacetType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; @@ -111,6 +114,25 @@ public class BuildoutFacet extends Facet implements return null; } + @NotNull + public static List getExtraPathForAllOpenModules() { + final List results = new ArrayList(); + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + for (Module module : ModuleManager.getInstance(project).getModules()) { + final BuildoutFacet buildoutFacet = getInstance(module); + if (buildoutFacet != null) { + for (String path : buildoutFacet.getConfiguration().getPaths()) { + final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); + if (file != null) { + results.add(file); + } + } + } + } + } + return results; + } + /** * Generates a sys.path[0:0] = [...] with paths that buildout script wants. * diff --git a/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java b/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java index 359ad9cf3ba0..a3146634ad4e 100644 --- a/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java +++ b/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java @@ -43,13 +43,16 @@ public class PythonTemplateContextType extends FileTypeBasedContextType { if (super.isInContext(file, offset)) { final PsiElement element = file.findElementAt(offset); if (element != null) { - return !(isAfterDot(element) || element instanceof PsiComment || element instanceof PyStringLiteralExpression || - isInsideParameterList(element)); + return !(isAfterDot(element) || element instanceof PsiComment || isInsideStringLiteral(element) || isInsideParameterList(element)); } } return false; } + private static boolean isInsideStringLiteral(@NotNull PsiElement element) { + return PsiTreeUtil.getParentOfType(element, PyStringLiteralExpression.class, false) != null; + } + private static boolean isInsideParameterList(@NotNull PsiElement element) { return PsiTreeUtil.getParentOfType(element, PyParameterList.class) != null; } diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 9d2c2232ecb0..3c4b23af6ee3 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -997,7 +997,28 @@ public class PyUtil { return target; } + /** + * @see #isPackage(PsiDirectory, boolean, PsiElement) + */ public static boolean isPackage(@NotNull PsiDirectory directory, @Nullable PsiElement anchor) { + return isPackage(directory, true, anchor); + } + + /** + * Checks that given PsiDirectory can be treated as Python package, i.e. it's either contains __init__.py or it's a namespace package + * (effectively any directory in Python 3.3 and above). Setuptools namespace packages can be checked as well, but it requires access to + * {@link PySetuptoolsNamespaceIndex} and may slow things down during update of project indexes. + * Also note that this method does not check that directory itself and its parents have valid importable names, + * use {@link PyNames#isIdentifier(String)} for this purpose. + * + * @param directory PSI directory to check + * @param checkSetupToolsPackages whether setuptools namespace packages should be considered as well + * @param anchor optional anchor element to determine language level + * @return whether given directory is Python package + * + * @see PyNames#isIdentifier(String) + */ + public static boolean isPackage(@NotNull PsiDirectory directory, boolean checkSetupToolsPackages, @Nullable PsiElement anchor) { if (directory.findFile(PyNames.INIT_DOT_PY) != null) { return true; } @@ -1007,7 +1028,7 @@ public class PyUtil { if (level.isAtLeast(LanguageLevel.PYTHON33)) { return true; } - return isSetuptoolsNamespacePackage(directory); + return checkSetupToolsPackages && isSetuptoolsNamespacePackage(directory); } public static boolean isPackage(@NotNull PsiFile file) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index a94f11e3d2c9..c03fe346b6e3 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -63,6 +63,12 @@ import static com.intellij.openapi.util.text.StringUtil.notNullize; * @author yole */ public class PyClassImpl extends PyBaseElementImpl implements PyClass { + public static class MROException extends Exception { + public MROException(String s) { + super(s); + } + } + public static final PyClass[] EMPTY_ARRAY = new PyClassImpl[0]; private List myInstanceAttributes; @@ -80,7 +86,28 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla @Nullable @Override public CachedValueProvider.Result> compute(@NotNull TypeEvalContext context) { - final List ancestorTypes = isNewStyleClass() ? getMROAncestorTypes(context) : getOldStyleAncestorTypes(context); + List ancestorTypes; + if (isNewStyleClass()) { + try { + ancestorTypes = getMROAncestorTypes(context); + } + catch (MROException e) { + ancestorTypes = getOldStyleAncestorTypes(context); + boolean hasUnresolvedAncestorTypes = false; + for (PyClassLikeType type : ancestorTypes) { + if (type == null) { + hasUnresolvedAncestorTypes = true; + break; + } + } + if (!hasUnresolvedAncestorTypes) { + ancestorTypes = Collections.singletonList(null); + } + } + } + else { + ancestorTypes = getOldStyleAncestorTypes(context); + } return CachedValueProvider.Result.create(ancestorTypes, PsiModificationTracker.MODIFICATION_COUNT); } } @@ -321,7 +348,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } @NotNull - private static List mroMerge(@NotNull List> sequences) { + private static List mroMerge(@NotNull List> sequences) throws MROException { List result = new LinkedList(); // need to insert to 0th position on linearize while (true) { // filter blank sequences @@ -335,6 +362,11 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla PyClassLikeType head = null; // to keep compiler happy; really head is assigned in the loop at least once. for (List seq : nonBlankSequences) { head = seq.get(0); + if (head == null) { + seq.remove(0); + found = true; + break; + } boolean head_in_tails = false; for (List tail_seq : nonBlankSequences) { if (tail_seq.indexOf(head) > 0) { // -1 is not found, 0 is head, >0 is tail. @@ -352,14 +384,16 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } if (!found) { // Inconsistent hierarchy results in TypeError - throw new IllegalStateException("Inconsistent class hierarchy"); + throw new MROException("Inconsistent class hierarchy"); } // our head is clean; result.add(head); // remove it from heads of other sequences - for (List seq : nonBlankSequences) { - if (Comparing.equal(seq.get(0), head)) { - seq.remove(0); + if (head != null) { + for (List seq : nonBlankSequences) { + if (Comparing.equal(seq.get(0), head)) { + seq.remove(0); + } } } } // we either return inside the loop or die by assertion @@ -367,9 +401,9 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla @NotNull private static List mroLinearize(@NotNull PyClassLikeType type, @NotNull Set seen, boolean addThisType, - @NotNull TypeEvalContext context) { + @NotNull TypeEvalContext context) throws MROException { if (seen.contains(type)) { - throw new IllegalStateException("Circular class inheritance"); + throw new MROException("Circular class inheritance"); } final List bases = type.getSuperClassTypes(context); List> lines = new ArrayList>(); @@ -1293,16 +1327,48 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } @NotNull - private List getMROAncestorTypes(@NotNull TypeEvalContext context) { + private List getMROAncestorTypes(@NotNull TypeEvalContext context) throws MROException { final PyType thisType = context.getType(this); if (thisType instanceof PyClassLikeType) { - try { - return mroLinearize((PyClassLikeType)thisType, new HashSet(), false, context); + final PyClassLikeType thisClassLikeType = (PyClassLikeType)thisType; + final List ancestorTypes = mroLinearize(thisClassLikeType, new HashSet(), false, context); + if (isOverriddenMRO(ancestorTypes, context)) { + ancestorTypes.add(null); } - catch (IllegalStateException ignored) { + return ancestorTypes; + } + else { + return Collections.emptyList(); + } + } + + private boolean isOverriddenMRO(@NotNull List ancestorTypes, @NotNull TypeEvalContext context) { + final List classes = new ArrayList(); + classes.add(this); + for (PyClassLikeType ancestorType : ancestorTypes) { + if (ancestorType instanceof PyClassType) { + final PyClassType classType = (PyClassType)ancestorType; + classes.add(classType.getPyClass()); } } - return Collections.emptyList(); + + final PyClass typeClass = PyBuiltinCache.getInstance(this).getClass("type"); + + for (PyClass cls : classes) { + final PyType metaClassType = cls.getMetaClassType(context); + if (metaClassType instanceof PyClassType) { + final PyClass metaClass = ((PyClassType)metaClassType).getPyClass(); + final PyFunction mroMethod = metaClass.findMethodByName(PyNames.MRO, true); + if (mroMethod != null) { + final PyClass mroClass = mroMethod.getContainingClass(); + if (mroClass != null && mroClass != typeClass) { + return true; + } + } + } + } + + return false; } @NotNull diff --git a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java index 11d4034fb42b..c9c7d636a1a1 100644 --- a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java +++ b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java @@ -41,6 +41,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.ZipUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; +import com.jetbrains.python.buildout.BuildoutFacet; import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil; import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.psi.resolve.PythonSdkPathCache; @@ -237,9 +238,12 @@ public class PySkeletonRefresher { final VirtualFile remoteSourcesDir = PySdkUtil.findAnyRemoteLibrary(sdk); final File remoteSources = remoteSourcesDir != null ? new File(remoteSourcesDir.getPath()) : null; - final VirtualFile[] classDirs = sdk.getRootProvider().getFiles(OrderRootType.CLASSES); + final List paths = new ArrayList(); - return Joiner.on(File.pathSeparator).join(ContainerUtil.mapNotNull(classDirs, new Function() { + paths.addAll(Arrays.asList(sdk.getRootProvider().getFiles(OrderRootType.CLASSES))); + paths.addAll(BuildoutFacet.getExtraPathForAllOpenModules()); + + return Joiner.on(File.pathSeparator).join(ContainerUtil.mapNotNull(paths, new Function() { @Override public Object fun(VirtualFile file) { diff --git a/python/testData/codeInsight/classMRO/UnresolvedClassesImpossibleToBuildMRO.py b/python/testData/codeInsight/classMRO/UnresolvedClassesImpossibleToBuildMRO.py new file mode 100644 index 000000000000..9514c0f31690 --- /dev/null +++ b/python/testData/codeInsight/classMRO/UnresolvedClassesImpossibleToBuildMRO.py @@ -0,0 +1,34 @@ +class EtagSupport(object): + pass + + +class LockableItem(EtagSupport): + pass + + +class Resource(LockableItem, _Unresolved): + pass + + +class CopyContainer(_Unresolved): + pass + + +class Navigation(_Unresolved): + pass + + +class Tabs(_Unresolved): + pass + + +class Collection(Resource): + pass + + +class Traversable(object): + pass + + +class ObjectManager(CopyContainer, Navigation, Tabs, _Unresolved, _Unresolved, Collection, Traversable): + pass diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/fallbackToOldStyleMROIfUnresolvedAncestorsAndC3Fails.py b/python/testData/inspections/PyUnresolvedReferencesInspection/fallbackToOldStyleMROIfUnresolvedAncestorsAndC3Fails.py new file mode 100644 index 000000000000..edd8344dfae9 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/fallbackToOldStyleMROIfUnresolvedAncestorsAndC3Fails.py @@ -0,0 +1,22 @@ +class X(Unresolved): + pass + + +class Y(Unresolved): + pass + + +class A(X, Y): + def foo(self): + pass + + +class B(Y, X): + pass + + +class C(A, B): # we don't know whether MRO is OK or not + pass + + +print(C.foo) # pass diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/noUnresolvedReferencesForClassesWithBadMRO.py b/python/testData/inspections/PyUnresolvedReferencesInspection/noUnresolvedReferencesForClassesWithBadMRO.py new file mode 100644 index 000000000000..600ec8e33a53 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/noUnresolvedReferencesForClassesWithBadMRO.py @@ -0,0 +1,26 @@ +class O(object): + pass + + +class X(O): + pass + + +class Y(O): + pass + + +class A(X, Y): + def foo(self): + pass + + +class B(Y, X): + pass + + +class C(A, B): # bad MRO + pass + + +print(C.foo) # pass diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/overriddenMRO.py b/python/testData/inspections/PyUnresolvedReferencesInspection/overriddenMRO.py new file mode 100644 index 000000000000..e1f25b3568c8 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/overriddenMRO.py @@ -0,0 +1,22 @@ +class A(object): + def foo(self): + return 0 + + +class B(object): + def bar(self): + return 0 + + +class MyMeta(type): + def mro(cls): + return A, B + + +class C(B): + __metaclass__ = MyMeta + + +c = C() +print(c.foo().lower()) # pass +print(c.bar().lower()) diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/overriddenMROInAncestors.py b/python/testData/inspections/PyUnresolvedReferencesInspection/overriddenMROInAncestors.py new file mode 100644 index 000000000000..15cd8ae700d5 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/overriddenMROInAncestors.py @@ -0,0 +1,28 @@ +class A(object): + def foo(self): + return 0 + + +class MyMeta(type): + def mro(cls): + return A, B + + +class MyMeta2(MyMeta): + pass + + +class B(object): + __metaclass__ = MyMeta2 + + def bar(self): + return 0 + + +class C(B): + pass + + +c = C() +print(c.foo().lower()) # pass +print(c.bar().lower()) diff --git a/python/testData/resolve/ResolveAttributesUsingOldStyleMROWhenUnresolvedAncestorsAndC3Fails.py b/python/testData/resolve/ResolveAttributesUsingOldStyleMROWhenUnresolvedAncestorsAndC3Fails.py new file mode 100644 index 000000000000..c279d67c9a4c --- /dev/null +++ b/python/testData/resolve/ResolveAttributesUsingOldStyleMROWhenUnresolvedAncestorsAndC3Fails.py @@ -0,0 +1,23 @@ +class X(Unresolved): + pass + + +class Y(Unresolved): + pass + + +class A(X, Y): + def foo(self): + pass + + +class B(Y, X): + pass + + +class C(A, B): # we don't know whether MRO is OK or not + pass + + +print(C.foo) +# diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index f317c6c20102..0675ba93cea4 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -474,7 +474,7 @@ public class PyQuickFixTest extends PyTestCase { public void testRemoveUnicodePrefixFromGluedStringNodesWithSlash() { runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() { public void run() { - myFixture.configureByFiles(getTestDataPath() + getTestName(false) + ".py"); + myFixture.configureByFile(getTestName(false) + ".py"); myFixture.checkHighlighting(true, false, false); final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U")); assertNotNull(intentionAction); @@ -488,7 +488,7 @@ public class PyQuickFixTest extends PyTestCase { public void testRemoveUnicodePrefixFromGluedStringNodesInParenthesis() { runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() { public void run() { - myFixture.configureByFiles(getTestDataPath() + getTestName(false) + ".py"); + myFixture.configureByFile(getTestName(false) + ".py"); myFixture.checkHighlighting(true, false, false); final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U")); assertNotNull(intentionAction); diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index 91a8955938cf..52089593aec6 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -567,4 +567,9 @@ public class PyResolveTest extends PyResolveTestCase { PyTargetExpression xyzzy = assertResolvesTo(PyTargetExpression.class, "xyzzy"); assertEquals("__init__", PsiTreeUtil.getParentOfType(xyzzy, PyFunction.class).getName()); } + + // PY-11401 + public void testResolveAttributesUsingOldStyleMROWhenUnresolvedAncestorsAndC3Fails() { + assertResolvesTo(PyFunction.class, "foo"); + } } diff --git a/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java b/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java index eb828b7eed8c..a6a2adc488c5 100644 --- a/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java +++ b/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java @@ -35,7 +35,7 @@ public class PyClassMROTest extends PyTestCase { // TypeError in Python public void testMROConflict() { - assertMRO(getClass("C")); + assertMRO(getClass("C"), "unknown"); } public void testCircularInheritance() { @@ -43,7 +43,7 @@ public class PyClassMROTest extends PyTestCase { myFixture.configureByFiles(getPath(testName), getPath(testName + "2")); final PyClass cls = myFixture.findElementByText("Foo", PyClass.class); assertNotNull(cls); - assertMRO(cls); + assertMRO(cls, "unknown"); } public void testExampleFromDoc1() { @@ -55,7 +55,7 @@ public class PyClassMROTest extends PyTestCase { } public void testExampleFromDoc3() { - assertMRO(getClass("G")); + assertMRO(getClass("G"), "unknown"); } public void testExampleFromDoc4() { @@ -71,6 +71,13 @@ public class PyClassMROTest extends PyTestCase { assertMRO(getClass("H"), "E", "F", "B", "G", "C", "D", "A", "object"); } + // PY-11401 + public void testUnresolvedClassesImpossibleToBuildMRO() { + assertMRO(getClass("ObjectManager"), + "CopyContainer", "unknown", "Navigation", "unknown", "Tabs", "unknown", "unknown", "unknown", "Collection", "Resource", + "LockableItem", "EtagSupport", "Traversable", "object", "unknown"); + } + public void assertMRO(@NotNull PyClass cls, @NotNull String... mro) { final List types = cls.getAncestorTypes(TypeEvalContext.codeInsightFallback(cls.getProject())); final List classNames = new ArrayList(); diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index b367fcb8089f..327cecabf147 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -440,6 +440,26 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doMultiFileTest("p1/__init__.py"); } + // PY-11401 + public void testNoUnresolvedReferencesForClassesWithBadMRO() { + doTest(); + } + + // PY-11401 + public void testFallbackToOldStyleMROIfUnresolvedAncestorsAndC3Fails() { + doTest(); + } + + // PY-11401 + public void testOverriddenMRO() { + doTest(); + } + + // PY-11401 + public void testOverriddenMROInAncestors() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() { diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index a5dd90c7896c..98ec7e480eda 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -68,6 +68,7 @@ checksum chmod classpath clazz +clion clob clojure cloneable diff --git a/xml/impl/resources/liveTemplates/zen_html.xml b/xml/impl/resources/liveTemplates/zen_html.xml index ec5a2d388562..76a1d65d4779 100644 --- a/xml/impl/resources/liveTemplates/zen_html.xml +++ b/xml/impl/resources/liveTemplates/zen_html.xml @@ -517,6 +517,15 @@