diff --git a/.idea/artifacts/jps.xml b/.idea/artifacts/jps.xml index dfbf48d9121b..50928bde9a11 100644 --- a/.idea/artifacts/jps.xml +++ b/.idea/artifacts/jps.xml @@ -11,7 +11,7 @@ - + diff --git a/.idea/modules.xml b/.idea/modules.xml index e6de17c97dfd..745b7901ffa3 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -51,6 +51,7 @@ + @@ -80,7 +81,6 @@ - diff --git a/RegExpSupport/test/test/BaseParseTestcase.java b/RegExpSupport/test/test/BaseParseTestcase.java index ccdf656619e3..e6cb0fc0d726 100644 --- a/RegExpSupport/test/test/BaseParseTestcase.java +++ b/RegExpSupport/test/test/BaseParseTestcase.java @@ -43,7 +43,7 @@ public abstract class BaseParseTestcase extends UsefulTestCase{ protected void setUp() throws Exception { super.setUp(); final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory(); - final TestFixtureBuilder builder = fixtureFactory.createFixtureBuilder(); + final TestFixtureBuilder builder = fixtureFactory.createFixtureBuilder(getName()); myFixture = fixtureFactory.createCodeInsightFixture(builder.getFixture()); myFixture.setTestDataPath(getTestDataPath()); diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index e78e38697911..6381e2e9eab8 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -77,7 +77,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir //noinspection GroovyAssignabilityCheck List implementationModules = [platformImplementationModules(), - "notNull", + "instrumentation-util", "platform-main", "java-psi-impl", "java-impl", @@ -170,7 +170,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir module("javac2") module("forms-compiler") module("forms_rt") - module("notNull") + module("instrumentation-util") } jar("jps-server.jar") { diff --git a/community-main.iml b/community-main.iml index a52ba14d3c83..0dbcfb09ce10 100644 --- a/community-main.iml +++ b/community-main.iml @@ -31,7 +31,7 @@ - + diff --git a/java/compiler/forms-compiler/forms-compiler.iml b/java/compiler/forms-compiler/forms-compiler.iml index ce591cf3173e..39ba1446f119 100644 --- a/java/compiler/forms-compiler/forms-compiler.iml +++ b/java/compiler/forms-compiler/forms-compiler.iml @@ -13,6 +13,7 @@ + diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java index b7a344dcf74e..b838594d8f6f 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java @@ -15,6 +15,7 @@ */ package com.intellij.uiDesigner.compiler; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.uiDesigner.UIFormXmlConstants; import com.intellij.uiDesigner.lw.*; import com.intellij.uiDesigner.shared.BorderType; @@ -28,7 +29,6 @@ import javax.swing.*; import javax.swing.border.Border; import java.awt.*; import java.io.*; -import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; @@ -40,7 +40,7 @@ import java.util.Map; */ public class AsmCodeGenerator { private final LwRootContainer myRootContainer; - private final ClassLoader myLoader; + private final InstrumentationClassFinder myFinder; private final ArrayList myErrors; private final ArrayList myWarnings; @@ -96,20 +96,20 @@ public class AsmCodeGenerator { } public AsmCodeGenerator(LwRootContainer rootContainer, - ClassLoader loader, + InstrumentationClassFinder finder, NestedFormLoader formLoader, final boolean ignoreCustomCreation, final ClassWriter classWriter) { myFormLoader = formLoader; myIgnoreCustomCreation = ignoreCustomCreation; - if (loader == null){ + if (finder == null){ throw new IllegalArgumentException("loader cannot be null"); } if (rootContainer == null){ throw new IllegalArgumentException("rootContainer cannot be null"); } myRootContainer = rootContainer; - myLoader = loader; + myFinder = finder; myErrors = new ArrayList(); myWarnings = new ArrayList(); @@ -210,9 +210,9 @@ public class AsmCodeGenerator { codeGen.generatePushValue(generator, value); } - static Class getComponentClass(String className, final ClassLoader classLoader) throws CodeGenerationException { + static InstrumentationClassFinder.PseudoClass getComponentClass(String className, final InstrumentationClassFinder finder) throws CodeGenerationException { try { - return Class.forName(className, false, classLoader); + return finder.loadClass(className); } catch (ClassNotFoundException e) { throw new CodeGenerationException(null, "Class not found: " + className); @@ -220,6 +220,9 @@ public class AsmCodeGenerator { catch(UnsupportedClassVersionError e) { throw new CodeGenerationException(null, "Unsupported class version error: " + className); } + catch (IOException e) { + throw new CodeGenerationException(null, e.getMessage(), e); + } } public static Type typeFromClassName(final String className) { @@ -252,7 +255,7 @@ public class AsmCodeGenerator { for (Iterator iterator = myPropertyCodeGenerators.values().iterator(); iterator.hasNext();) { PropertyCodeGenerator propertyCodeGenerator = (PropertyCodeGenerator)iterator.next(); - propertyCodeGenerator.generateClassStart(this, name, myLoader); + propertyCodeGenerator.generateClassStart(this, name, myFinder); } } @@ -394,28 +397,30 @@ public class AsmCodeGenerator { myIdToLocalMap.put(lwComponent.getId(), new Integer(componentLocal)); - Class componentClass = getComponentClass(className, myLoader); + InstrumentationClassFinder.PseudoClass componentClass = getComponentClass(className, myFinder); validateFieldBinding(lwComponent, componentClass); if (myIgnoreCustomCreation) { - boolean creatable = true; - if ((componentClass.getModifiers() & (Modifier.PRIVATE | Modifier.ABSTRACT)) != 0) { - creatable = false; - } - else { - try { - final Constructor constructor = componentClass.getConstructor(new Class[0]); - if ((constructor.getModifiers() & Modifier.PUBLIC) == 0) { + try { + boolean creatable = true; + if ((componentClass.getModifiers() & (Modifier.PRIVATE | Modifier.ABSTRACT)) != 0) { + creatable = false; + } + else { + if (!componentClass.hasDefaultPublicConstructor()) { creatable = false; } } - catch(NoSuchMethodException ex) { - creatable = false; + if (!creatable) { + componentClass = Utils.suggestReplacementClass(componentClass); + componentType = Type.getType(componentClass.getDescriptor()); } } - if (!creatable) { - componentClass = Utils.suggestReplacementClass(componentClass); - componentType = Type.getType(componentClass); + catch (ClassNotFoundException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); + } + catch (IOException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); } } @@ -468,12 +473,11 @@ public class AsmCodeGenerator { } } - private int getNestedFormComponent(GeneratorAdapter generator, Class componentClass, int formLocal) throws CodeGenerationException { + private int getNestedFormComponent(GeneratorAdapter generator, InstrumentationClassFinder.PseudoClass componentClass, int formLocal) throws CodeGenerationException { final Type componentType = Type.getType(JComponent.class); int componentLocal = generator.newLocal(componentType); generator.loadLocal(formLocal); - generator.invokeVirtual(Type.getType(componentClass), - new Method(GET_ROOT_COMPONENT_METHOD_NAME, componentType, new Type[0])); + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method(GET_ROOT_COMPONENT_METHOD_NAME, componentType, new Type[0])); generator.storeLocal(componentLocal); return componentLocal; } @@ -502,7 +506,7 @@ public class AsmCodeGenerator { } private void generateComponentProperties(final LwComponent lwComponent, - final Class componentClass, + final InstrumentationClassFinder.PseudoClass componentClass, final GeneratorAdapter generator, final int componentLocal) throws CodeGenerationException { // introspected properties @@ -543,7 +547,12 @@ public class AsmCodeGenerator { else { setterClass = Class.forName(propertyClass); } - componentClass.getMethod(property.getWriteMethodName(), new Class[] { setterClass } ); + //componentClass.getMethod(property.getWriteMethodName(), new Class[] { setterClass } ); + final String descriptor = "(L"+setterClass.getName().replace('.', '/') + ";)V"; + final InstrumentationClassFinder.PseudoMethod setter = componentClass.findMethod(property.getWriteMethodName(), descriptor); + if (setter == null) { + continue; + } } catch (Exception e) { continue; @@ -551,9 +560,16 @@ public class AsmCodeGenerator { } final PropertyCodeGenerator propGen = (PropertyCodeGenerator) myPropertyCodeGenerators.get(propertyClass); - if (propGen != null && propGen.generateCustomSetValue(lwComponent, componentClass, property, - generator, componentLocal, myClassName)) { - continue; + try { + if (propGen != null && propGen.generateCustomSetValue(lwComponent, componentClass, property, generator, componentLocal, myClassName)) { + continue; + } + } + catch (IOException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); + } + catch (ClassNotFoundException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); } generator.loadLocal(componentLocal); @@ -602,7 +618,7 @@ public class AsmCodeGenerator { Type declaringType = (property.getDeclaringClassName() != null) ? typeFromClassName(property.getDeclaringClassName()) - : Type.getType(componentClass); + : Type.getType(componentClass.getDescriptor()); generator.invokeVirtual(declaringType, new Method(property.getWriteMethodName(), Type.VOID_TYPE, new Type[] { setterArgType } )); } @@ -611,7 +627,7 @@ public class AsmCodeGenerator { } private void generateClientProperties(final LwComponent lwComponent, - final Class componentClass, + final InstrumentationClassFinder.PseudoClass componentClass, final GeneratorAdapter generator, final int componentLocal) throws CodeGenerationException { HashMap props = lwComponent.getDelegeeClientProperties(); @@ -652,7 +668,7 @@ public class AsmCodeGenerator { } } - Type componentType = Type.getType(componentClass); + Type componentType = Type.getType(componentClass.getDescriptor()); Type objectType = Type.getType(Object.class); generator.invokeVirtual(componentType, new Method("putClientProperty", Type.VOID_TYPE, new Type[] { objectType, objectType } )); @@ -664,7 +680,7 @@ public class AsmCodeGenerator { if (component instanceof LwNestedForm) return; int componentLocal = ((Integer) myIdToLocalMap.get(component.getId())).intValue(); final LayoutCodeGenerator layoutCodeGenerator = getComponentCodeGenerator(component.getParent()); - Class componentClass = getComponentClass(layoutCodeGenerator.mapComponentClass(component.getComponentClassName()), myLoader); + InstrumentationClassFinder.PseudoClass componentClass = getComponentClass(layoutCodeGenerator.mapComponentClass(component.getComponentClassName()), myFinder); final LwIntrospectedProperty[] introspectedProperties = component.getAssignedIntrospectedProperties(); for (int i = 0; i < introspectedProperties.length; i++) { @@ -681,7 +697,7 @@ public class AsmCodeGenerator { generator.loadLocal(targetLocal); Type declaringType = (property.getDeclaringClassName() != null) ? typeFromClassName(property.getDeclaringClassName()) - : Type.getType(componentClass); + : Type.getType(componentClass.getDescriptor()); generator.invokeVirtual(declaringType, new Method(property.getWriteMethodName(), Type.VOID_TYPE, new Type[] { typeFromClassName(property.getPropertyClassName()) } )); @@ -702,33 +718,45 @@ public class AsmCodeGenerator { private void generateButtonGroups(final LwRootContainer rootContainer, final GeneratorAdapter generator) throws CodeGenerationException { IButtonGroup[] groups = rootContainer.getButtonGroups(); if (groups.length > 0) { - int groupLocal = generator.newLocal(ourButtonGroupType); - for(int groupIndex=0; groupIndex 0) { - generator.newInstance(ourButtonGroupType); - generator.dup(); - generator.invokeConstructor(ourButtonGroupType, Method.getMethod("void ()")); - generator.storeLocal(groupLocal); + if (ids.length > 0) { + generator.newInstance(ourButtonGroupType); + generator.dup(); + generator.invokeConstructor(ourButtonGroupType, Method.getMethod("void ()")); + generator.storeLocal(groupLocal); - if (groups [groupIndex].isBound() && !myIgnoreCustomCreation) { - validateFieldClass(groups [groupIndex].getName(), ButtonGroup.class, null); - generator.loadThis(); - generator.loadLocal(groupLocal); - generator.putField(getMainClassType(), groups [groupIndex].getName(), ourButtonGroupType); - } - - for(int i = 0; i= 0) { generator.loadLocal(componentLocal); generator.push(textWithMnemonic.myText); - generator.invokeVirtual(Type.getType(componentClass), + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method(property.getWriteMethodName(), Type.VOID_TYPE, new Type[] { Type.getType(String.class) } )); String setMnemonicMethodName; - if (AbstractButton.class.isAssignableFrom(componentClass)) { + if (abstractButtonClass.isAssignableFrom(componentClass)) { setMnemonicMethodName = "setMnemonic"; } else { @@ -89,14 +93,14 @@ public class StringPropertyCodeGenerator extends PropertyCodeGenerator implement generator.loadLocal(componentLocal); generator.push(textWithMnemonic.getMnemonicChar()); - generator.invokeVirtual(Type.getType(componentClass), + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method(setMnemonicMethodName, Type.VOID_TYPE, new Type[] { Type.CHAR_TYPE } )); if (myHaveSetDisplayedMnemonicIndex) { generator.loadLocal(componentLocal); generator.push(textWithMnemonic.myMnemonicIndex); - generator.invokeVirtual(Type.getType(componentClass), + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method("setDisplayedMnemonicIndex", Type.VOID_TYPE, new Type[] { Type.INT_TYPE } )); } @@ -105,7 +109,7 @@ public class StringPropertyCodeGenerator extends PropertyCodeGenerator implement } else { Method method; - if (AbstractButton.class.isAssignableFrom(componentClass)) { + if (abstractButtonClass.isAssignableFrom(componentClass)) { myClassesRequiringLoadButtonText.add(formClassName); method = myLoadButtonTextMethod; } diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java index 4b28e2d04628..79fb947cacb5 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java @@ -15,6 +15,7 @@ */ package com.intellij.uiDesigner.compiler; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.lw.*; import org.jdom.Document; @@ -28,6 +29,7 @@ import javax.swing.*; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.awt.*; +import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.lang.reflect.Constructor; @@ -43,306 +45,323 @@ import java.util.Set; * NOTE: the class must be compilable with JDK 1.3, so any methods and filds introduced in 1.4 or later must not be used */ public final class Utils { - public static final String FORM_NAMESPACE = "http://www.intellij.com/uidesigner/form/"; - private static final SAXParser SAX_PARSER = createParser(); + public static final String FORM_NAMESPACE = "http://www.intellij.com/uidesigner/form/"; + private static final SAXParser SAX_PARSER = createParser(); - private Utils() { + private Utils() { + } + + private static SAXParser createParser() { + try { + return SAXParserFactory.newInstance().newSAXParser(); + } + catch (Exception e) { + return null; + } + } + + /** + * @param provider if null, no classes loaded and no properties read + */ + public static LwRootContainer getRootContainer(final String formFileContent, final PropertiesProvider provider) throws Exception { + if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { + throw new AlienFormFileException(); } - private static SAXParser createParser() { - try { - return SAXParserFactory.newInstance().newSAXParser(); - } - catch (Exception e) { - return null; + final Document document = new SAXBuilder().build(new StringReader(formFileContent), "UTF-8"); + + return getRootContainerFromDocument(document, provider); + } + + /** + * Get root from the url + * + * @param formFile the document URL + * @param provider the provider + * @return the root container + * @throws Exception if there is a problem with parsing DOM + */ + public static LwRootContainer getRootContainer(final URL formFile, final PropertiesProvider provider) throws Exception { + final Document document = new SAXBuilder().build(formFile); + return getRootContainerFromDocument(document, provider); + } + + + /** + * Get root from the document + * + * @param document the parsed document + * @param provider the provider + * @return the root container + * @throws Exception if there is a problem with parsing DOM + */ + private static LwRootContainer getRootContainerFromDocument(Document document, PropertiesProvider provider) throws Exception { + final LwRootContainer root = new LwRootContainer(); + root.read(document.getRootElement(), provider); + return root; + } + + public static LwRootContainer getRootContainer(final InputStream stream, final PropertiesProvider provider) throws Exception { + final Document document = new SAXBuilder().build(stream, "UTF-8"); + + return getRootContainerFromDocument(document, provider); + } + + public synchronized static String getBoundClassName(final String formFileContent) throws Exception { + if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { + throw new AlienFormFileException(); + } + + final String[] className = new String[]{null}; + try { + SAX_PARSER.parse(new InputSource(new StringReader(formFileContent)), new DefaultHandler() { + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if ("form".equals(qName)) { + className[0] = attributes.getValue("", "bind-to-class"); + throw new SAXException("stop parsing"); + } } + }); + } + catch (Exception e) { + // Do nothing. } - /** - * @param provider if null, no classes loaded and no properties read - */ - public static LwRootContainer getRootContainer(final String formFileContent, final PropertiesProvider provider) throws Exception { - if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { - throw new AlienFormFileException(); - } + return className[0]; + } - final Document document = new SAXBuilder().build(new StringReader(formFileContent), "UTF-8"); - - return getRootContainerFromDocument(document, provider); - } - - /** - * Get root from the url - * - * @param formFile the document URL - * @param provider the provider - * @return the root container - * @throws Exception if there is a problem with parsing DOM - */ - public static LwRootContainer getRootContainer(final URL formFile, final PropertiesProvider provider) throws Exception { - final Document document = new SAXBuilder().build(formFile); - return getRootContainerFromDocument(document, provider); - } - - - /** - * Get root from the document - * - * @param document the parsed document - * @param provider the provider - * @return the root container - * @throws Exception if there is a problem with parsing DOM - */ - private static LwRootContainer getRootContainerFromDocument(Document document, PropertiesProvider provider) throws Exception { - final LwRootContainer root = new LwRootContainer(); - root.read(document.getRootElement(), provider); - return root; - } - - public static LwRootContainer getRootContainer(final InputStream stream, final PropertiesProvider provider) throws Exception { - final Document document = new SAXBuilder().build(stream, "UTF-8"); - - return getRootContainerFromDocument(document, provider); - } - - public synchronized static String getBoundClassName(final String formFileContent) throws Exception { - if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { - throw new AlienFormFileException(); - } - - final String[] className = new String[]{null}; - try { - SAX_PARSER.parse(new InputSource(new StringReader(formFileContent)), new DefaultHandler() { - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - if ("form".equals(qName)) { - className[0] = attributes.getValue("", "bind-to-class"); - throw new SAXException("stop parsing"); - } - } - }); - } - catch (Exception e) { - // Do nothing. - } - - return className[0]; - } - - /** - * Validates that specified class represents {@link javax.swing.JComponent} with - * empty constructor. - * - * @return descriptive human readable error message or null if - * no errors were detected. - */ + /** + * Validates that specified class represents {@link javax.swing.JComponent} with + * empty constructor. + * + * @return descriptive human readable error message or null if + * no errors were detected. + */ public static String validateJComponentClass(final ClassLoader loader, final String className, final boolean validateConstructor) { if (loader == null) { - throw new IllegalArgumentException("loader cannot be null"); - } - if (className == null) { - throw new IllegalArgumentException("className cannot be null"); - } + throw new IllegalArgumentException("loader cannot be null"); + } + if (className == null) { + throw new IllegalArgumentException("className cannot be null"); + } - // These classes are not visible for passed class loader! - if ("com.intellij.uiDesigner.HSpacer".equals(className) || "com.intellij.uiDesigner.VSpacer".equals(className)) { - return null; - } + // These classes are not visible for passed class loader! + if ("com.intellij.uiDesigner.HSpacer".equals(className) || "com.intellij.uiDesigner.VSpacer".equals(className)) { + return null; + } final Class aClass; - try { + try { aClass = Class.forName(className, false, loader); - } - catch (final ClassNotFoundException exc) { - return "Class \"" + className + "\"not found"; - } - catch (NoClassDefFoundError exc) { - return "Cannot load class " + className + ": " + exc.getMessage(); - } - catch (ExceptionInInitializerError exc) { - return "Cannot initialize class " + className + ": " + exc.getMessage(); - } - catch (UnsupportedClassVersionError exc) { - return "Unsupported class version error: " + className; - } + } + catch (final ClassNotFoundException exc) { + return "Class \"" + className + "\"not found"; + } + catch (NoClassDefFoundError exc) { + return "Cannot load class " + className + ": " + exc.getMessage(); + } + catch (ExceptionInInitializerError exc) { + return "Cannot initialize class " + className + ": " + exc.getMessage(); + } + catch (UnsupportedClassVersionError exc) { + return "Unsupported class version error: " + className; + } - if (validateConstructor) { + if (validateConstructor) { try { final Constructor constructor = aClass.getConstructor(new Class[0]); if ((constructor.getModifiers() & Modifier.PUBLIC) == 0) { - return "Class \"" + className + "\" does not have default public constructor"; - } - } + return "Class \"" + className + "\" does not have default public constructor"; + } + } catch (final Exception exc) { return "Class \"" + className + "\" does not have default constructor"; } } - // Check that JComponent is accessible via the loader + // Check that JComponent is accessible via the loader if (!JComponent.class.isAssignableFrom(aClass)) { - return "Class \"" + className + "\" is not an instance of javax.swing.JComponent"; - } + return "Class \"" + className + "\" is not an instance of javax.swing.JComponent"; + } - return null; + return null; + } + + public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader) + throws CodeGenerationException, RecursiveFormNestingException { + validateNestedFormLoop(formName, nestedFormLoader, null); + } + + public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader, final String targetForm) + throws CodeGenerationException, RecursiveFormNestingException { + HashSet usedFormNames = new HashSet(); + if (targetForm != null) { + usedFormNames.add(targetForm); } + validateNestedFormLoop(usedFormNames, formName, nestedFormLoader); + } - public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader) - throws CodeGenerationException, RecursiveFormNestingException { - validateNestedFormLoop(formName, nestedFormLoader, null); + private static void validateNestedFormLoop(final Set usedFormNames, final String formName, final NestedFormLoader nestedFormLoader) + throws CodeGenerationException, RecursiveFormNestingException { + if (usedFormNames.contains(formName)) { + throw new RecursiveFormNestingException(); } - - public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader, final String targetForm) - throws CodeGenerationException, RecursiveFormNestingException { - HashSet usedFormNames = new HashSet(); - if (targetForm != null) { - usedFormNames.add(targetForm); - } - validateNestedFormLoop(usedFormNames, formName, nestedFormLoader); + usedFormNames.add(formName); + final LwRootContainer rootContainer; + try { + rootContainer = nestedFormLoader.loadForm(formName); } - - private static void validateNestedFormLoop(final Set usedFormNames, final String formName, final NestedFormLoader nestedFormLoader) - throws CodeGenerationException, RecursiveFormNestingException { - if (usedFormNames.contains(formName)) { - throw new RecursiveFormNestingException(); - } - usedFormNames.add(formName); - final LwRootContainer rootContainer; - try { - rootContainer = nestedFormLoader.loadForm(formName); - } - catch (Exception e) { - throw new CodeGenerationException(null, "Error loading nested form: " + e.getMessage(), e); - } - final Set thisFormNestedForms = new HashSet(); - final CodeGenerationException[] validateExceptions = new CodeGenerationException[1]; - final RecursiveFormNestingException[] recursiveNestingExceptions = new RecursiveFormNestingException[1]; - rootContainer.accept(new ComponentVisitor() { - public boolean visit(final IComponent component) { - if (component instanceof LwNestedForm) { - LwNestedForm nestedForm = (LwNestedForm)component; - if (!thisFormNestedForms.contains(nestedForm.getFormFileName())) { - thisFormNestedForms.add(nestedForm.getFormFileName()); - try { - validateNestedFormLoop(usedFormNames, nestedForm.getFormFileName(), nestedFormLoader); - } - catch (RecursiveFormNestingException e) { - recursiveNestingExceptions[0] = e; - return false; - } - catch (CodeGenerationException e) { - validateExceptions[0] = e; - return false; - } - } - } - return true; - } - }); - if (recursiveNestingExceptions[0] != null) { - throw recursiveNestingExceptions[0]; - } - if (validateExceptions[0] != null) { - throw validateExceptions[0]; - } + catch (Exception e) { + throw new CodeGenerationException(null, "Error loading nested form: " + e.getMessage(), e); } - - public static String findNotEmptyPanelWithXYLayout(final IComponent component) { - if (!(component instanceof IContainer)) { - return null; - } - final IContainer container = (IContainer)component; - if (container.getComponentCount() == 0) { - return null; - } - if (container.isXY()) { - return container.getId(); - } - for (int i = 0; i < container.getComponentCount(); i++) { - String id = findNotEmptyPanelWithXYLayout(container.getComponent(i)); - if (id != null) { - return id; - } - } - return null; - } - - public static int getHGap(LayoutManager layout) { - if (layout instanceof BorderLayout) { - return ((BorderLayout)layout).getHgap(); - } - if (layout instanceof CardLayout) { - return ((CardLayout)layout).getHgap(); - } - return 0; - } - - public static int getVGap(LayoutManager layout) { - if (layout instanceof BorderLayout) { - return ((BorderLayout)layout).getVgap(); - } - if (layout instanceof CardLayout) { - return ((CardLayout)layout).getVgap(); - } - return 0; - } - - public static int getCustomCreateComponentCount(final IContainer container) { - final int[] result = new int[1]; - result[0] = 0; - container.accept(new ComponentVisitor() { - public boolean visit(IComponent c) { - if (c.isCustomCreate()) { - result[0]++; - } - return true; - } - }); - return result[0]; - } - - public static Class suggestReplacementClass(Class componentClass) { - while (true) { - componentClass = componentClass.getSuperclass(); - if (componentClass.equals(JComponent.class)) { - return JPanel.class; - } - if ((componentClass.getModifiers() & (Modifier.ABSTRACT | Modifier.PRIVATE)) != 0) { - continue; - } + final Set thisFormNestedForms = new HashSet(); + final CodeGenerationException[] validateExceptions = new CodeGenerationException[1]; + final RecursiveFormNestingException[] recursiveNestingExceptions = new RecursiveFormNestingException[1]; + rootContainer.accept(new ComponentVisitor() { + public boolean visit(final IComponent component) { + if (component instanceof LwNestedForm) { + LwNestedForm nestedForm = (LwNestedForm)component; + if (!thisFormNestedForms.contains(nestedForm.getFormFileName())) { + thisFormNestedForms.add(nestedForm.getFormFileName()); try { - componentClass.getConstructor(new Class[]{}); + validateNestedFormLoop(usedFormNames, nestedForm.getFormFileName(), nestedFormLoader); } - catch (NoSuchMethodException ex) { - continue; + catch (RecursiveFormNestingException e) { + recursiveNestingExceptions[0] = e; + return false; } - return componentClass; + catch (CodeGenerationException e) { + validateExceptions[0] = e; + return false; + } + } } + return true; + } + }); + if (recursiveNestingExceptions[0] != null) { + throw recursiveNestingExceptions[0]; } + if (validateExceptions[0] != null) { + throw validateExceptions[0]; + } + } - public static int alignFromConstraints(final GridConstraints gc, final boolean horizontal) { - int anchor = gc.getAnchor(); - int fill = gc.getFill(); - int leftMask = horizontal ? GridConstraints.ANCHOR_WEST : GridConstraints.ANCHOR_NORTH; - int rightMask = horizontal ? GridConstraints.ANCHOR_EAST : GridConstraints.ANCHOR_SOUTH; - int fillMask = horizontal ? GridConstraints.FILL_HORIZONTAL : GridConstraints.FILL_VERTICAL; - if ((fill & fillMask) != 0) return GridConstraints.ALIGN_FILL; - if ((anchor & rightMask) != 0) return GridConstraints.ALIGN_RIGHT; - if ((anchor & leftMask) != 0) return GridConstraints.ALIGN_LEFT; - return GridConstraints.ALIGN_CENTER; + public static String findNotEmptyPanelWithXYLayout(final IComponent component) { + if (!(component instanceof IContainer)) { + return null; } + final IContainer container = (IContainer)component; + if (container.getComponentCount() == 0) { + return null; + } + if (container.isXY()) { + return container.getId(); + } + for (int i = 0; i < container.getComponentCount(); i++) { + String id = findNotEmptyPanelWithXYLayout(container.getComponent(i)); + if (id != null) { + return id; + } + } + return null; + } - public static boolean isBoundField(IComponent component, String fieldName) { - if (fieldName.equals(component.getBinding())) { - return true; - } - if (component instanceof IContainer) { - IContainer container = (IContainer)component; - for (int i = 0; i < container.getComponentCount(); i++) { - if (isBoundField(container.getComponent(i), fieldName)) { - return true; - } - } - } - return false; + public static int getHGap(LayoutManager layout) { + if (layout instanceof BorderLayout) { + return ((BorderLayout)layout).getHgap(); } + if (layout instanceof CardLayout) { + return ((CardLayout)layout).getHgap(); + } + return 0; + } + + public static int getVGap(LayoutManager layout) { + if (layout instanceof BorderLayout) { + return ((BorderLayout)layout).getVgap(); + } + if (layout instanceof CardLayout) { + return ((CardLayout)layout).getVgap(); + } + return 0; + } + + public static int getCustomCreateComponentCount(final IContainer container) { + final int[] result = new int[1]; + result[0] = 0; + container.accept(new ComponentVisitor() { + public boolean visit(IComponent c) { + if (c.isCustomCreate()) { + result[0]++; + } + return true; + } + }); + return result[0]; + } + + public static Class suggestReplacementClass(Class componentClass) { + while (true) { + componentClass = componentClass.getSuperclass(); + if (componentClass.equals(JComponent.class)) { + return JPanel.class; + } + if ((componentClass.getModifiers() & (Modifier.ABSTRACT | Modifier.PRIVATE)) != 0) { + continue; + } + try { + componentClass.getConstructor(new Class[]{}); + } + catch (NoSuchMethodException ex) { + continue; + } + return componentClass; + } + } + + public static InstrumentationClassFinder.PseudoClass suggestReplacementClass(InstrumentationClassFinder.PseudoClass componentClass) throws ClassNotFoundException, IOException { + final InstrumentationClassFinder.PseudoClass jComponentClass = componentClass.getFinder().loadClass(JComponent.class.getName()); + while (true) { + componentClass = componentClass.getSuperClass(); + if (componentClass.equals(jComponentClass)) { + return componentClass.getFinder().loadClass(JPanel.class.getName()); + } + if ((componentClass.getModifiers() & (Modifier.ABSTRACT | Modifier.PRIVATE)) != 0) { + continue; + } + if (!componentClass.hasDefaultPublicConstructor()) { + continue; + } + return componentClass; + } + } + + public static int alignFromConstraints(final GridConstraints gc, final boolean horizontal) { + int anchor = gc.getAnchor(); + int fill = gc.getFill(); + int leftMask = horizontal ? GridConstraints.ANCHOR_WEST : GridConstraints.ANCHOR_NORTH; + int rightMask = horizontal ? GridConstraints.ANCHOR_EAST : GridConstraints.ANCHOR_SOUTH; + int fillMask = horizontal ? GridConstraints.FILL_HORIZONTAL : GridConstraints.FILL_VERTICAL; + if ((fill & fillMask) != 0) return GridConstraints.ALIGN_FILL; + if ((anchor & rightMask) != 0) return GridConstraints.ALIGN_RIGHT; + if ((anchor & leftMask) != 0) return GridConstraints.ALIGN_LEFT; + return GridConstraints.ALIGN_CENTER; + } + + public static boolean isBoundField(IComponent component, String fieldName) { + if (fieldName.equals(component.getBinding())) { + return true; + } + if (component instanceof IContainer) { + IContainer container = (IContainer)component; + for (int i = 0; i < container.getComponentCount(); i++) { + if (isBoundField(container.getComponent(i), fieldName)) { + return true; + } + } + } + return false; + } } diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index f517eff750db..d9d39953f177 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -14,7 +14,7 @@ - + diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index fc7c7d7b7eb8..3aef0d599083 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -70,8 +70,7 @@ import org.jetbrains.jps.client.CompileServerClient; import org.jetbrains.jps.server.ClasspathBootstrap; import org.jetbrains.jps.server.Server; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; +import javax.tools.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -586,6 +585,10 @@ public class CompileServerManager implements ApplicationComponent{ cmdLine.addParameter("-XX:ReservedCodeCacheSize=64m"); cmdLine.addParameter("-Xmx" + Registry.intValue("compiler.server.heap.size") + "m"); cmdLine.addParameter("-Djava.awt.headless=true"); + final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION); + if (shouldGenerateIndex != null) { + cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex); + } //noinspection ConstantConditions if (pingInterval > 0L) { cmdLine.addParameter("-D" + GlobalOptions.PING_INTERVAL_MS_OPTION + "=" + pingInterval); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java index 39d8996e296a..f4353c85a8e5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java @@ -27,6 +27,7 @@ import javax.tools.*; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.lang.reflect.Field; import java.net.URI; import java.util.List; import java.util.concurrent.BlockingQueue; @@ -145,6 +146,18 @@ class CompAPIDriver { assert !processing; //assert myCompilationResults.isEmpty() : myCompilationResults; myCompilationResults.clear(); + cleanupInternalFields(); + } + + private static void cleanupInternalFields() { + try { + Field freelist = Class.forName("com.sun.tools.javac.util.SharedNameTable").getDeclaredField("freelist"); + freelist.setAccessible(true); + freelist.set(null, com.sun.tools.javac.util.List.nil()); + } + catch (Exception ignored) { + + } } public void offerClassFile(URI uri, byte[] bytes) { diff --git a/java/compiler/notNull/notNull.iml b/java/compiler/instrumentation-util/instrumentation-util.iml similarity index 100% rename from java/compiler/notNull/notNull.iml rename to java/compiler/instrumentation-util/instrumentation-util.iml diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/InstrumentationClassFinder.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java similarity index 71% rename from jps/jps-builders/src/org/jetbrains/jps/incremental/java/InstrumentationClassFinder.java rename to java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java index 8b2ee439af91..de009b37c9bf 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/InstrumentationClassFinder.java +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java @@ -1,10 +1,7 @@ -package org.jetbrains.jps.incremental.java; +package com.intellij.compiler.instrumentation; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.objectweb.asm.Attribute; import org.objectweb.asm.ClassReader; +import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.EmptyVisitor; import sun.misc.Resource; @@ -12,6 +9,7 @@ import sun.misc.Resource; import java.io.*; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLClassLoader; import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -23,22 +21,81 @@ import java.util.zip.ZipFile; public class InstrumentationClassFinder { private static final PseudoClass[] EMPTY_PSEUDOCLASS_ARRAY = new PseudoClass[0]; private static final String CLASS_RESOURCE_EXTENSION = ".class"; + private static final URL[] URL_EMPTY_ARRAY = new URL[0]; private final Map myLoaded = new HashMap(); // className -> class object private final ClassFinderClasspath myPlatformClasspath; private final ClassFinderClasspath myClasspath; + private final URL[] myPlatformUrls; + private final URL[] myClasspathUrls; + private ClassLoader myLoader; + private byte[] myBuffer; - public InstrumentationClassFinder(final URL[] platformClasspath, final URL[] classpath) { - myPlatformClasspath = new ClassFinderClasspath(platformClasspath); - myClasspath = new ClassFinderClasspath(classpath); + public InstrumentationClassFinder(final URL[] cp) { + this(URL_EMPTY_ARRAY, cp); + } + + public InstrumentationClassFinder(final URL[] platformUrls, final URL[] classpathUrls) { + myPlatformUrls = platformUrls; + myClasspathUrls = classpathUrls; + myPlatformClasspath = new ClassFinderClasspath(platformUrls); + myClasspath = new ClassFinderClasspath(classpathUrls); + } + + // compatibility with legacy code requiring ClassLoader + public ClassLoader getLoader() { + ClassLoader loader = myLoader; + if (loader != null) { + return loader; + } + final URLClassLoader platformLoader = myPlatformUrls.length > 0 ? new URLClassLoader(myPlatformUrls, null) : null; + final ClassLoader cpLoader = new URLClassLoader(myClasspathUrls, platformLoader); + loader = new ClassLoader(cpLoader) { + + public InputStream getResourceAsStream(String name) { + InputStream is = null; + is = super.getResourceAsStream(name); + if (is == null) { + try { + is = InstrumentationClassFinder.this.getResourceAsStream(name); + } + catch (IOException ignored) { + } + } + return is; + } + + protected Class findClass(String name) throws ClassNotFoundException { + final InputStream is = lookupClassBeforeClasspath(name.replace('.', '/')); + if (is == null) { + throw new ClassNotFoundException(name); + } + try { + final byte[] bytes = loadBytes(is); + return defineClass(name, bytes, 0, bytes.length); + } + finally { + try { + is.close(); + } + catch (IOException ignored) { + } + } + } + }; + myLoader = loader; + return loader; } public void releaseResources() { myPlatformClasspath.releaseResources(); myClasspath.releaseResources(); myLoaded.clear(); + myBuffer = null; + myLoader = null; } - public PseudoClass loadClass(final String internalName) throws IOException, ClassNotFoundException{ + public PseudoClass loadClass(final String name) throws IOException, ClassNotFoundException{ + final String internalName = name.replace('.', '/'); // normalize final PseudoClass aClass = myLoaded.get(internalName); if (aClass != null) { return aClass; @@ -81,12 +138,28 @@ public class InstrumentationClassFinder { } } - @Nullable + public InputStream getResourceAsStream(String resourceName) throws IOException { + InputStream is = null; + + Resource resource = myPlatformClasspath.getResource(resourceName, false); + if (resource != null) { + is = resource.getInputStream(); + } + + if (is == null) { + resource = myClasspath.getResource(resourceName, false); + if (resource != null) { + is = resource.getInputStream(); + } + } + + return is; + } + protected InputStream lookupClassBeforeClasspath(final String internalClassName) { return null; } - @Nullable protected InputStream lookupClassAfterClasspath(final String internalClassName) { return null; } @@ -97,20 +170,61 @@ public class InstrumentationClassFinder { reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - return new PseudoClass(visitor.myName, visitor.mySuperclassName, visitor.myInterfaces, visitor.myIsInterface); + return new PseudoClass(visitor.myName, visitor.mySuperclassName, visitor.myInterfaces, visitor.myModifiers, visitor.myMethods); } public final class PseudoClass { private final String myName; private final String mySuperClass; private final String[] myInterfaces; - private final boolean isInterface; + private final int myModifiers; + private final List myMethods; - private PseudoClass(final String name, final String superClass, final String[] interfaces, final boolean anInterface) { + private PseudoClass(final String name, final String superClass, final String[] interfaces, final int modifiers, List methods) { myName = name; mySuperClass = superClass; myInterfaces = interfaces; - isInterface = anInterface; + myModifiers = modifiers; + myMethods = methods; + } + + public int getModifiers() { + return myModifiers; + } + + public boolean isInterface() { + return (myModifiers & Opcodes.ACC_INTERFACE) > 0; + } + + public String getName() { + return myName; + } + + public List getMethods() { + return myMethods; + } + + public List findMethods(String name) { + final List result = new ArrayList(); + for (PseudoMethod method : myMethods) { + if (method.getName().equals(name)){ + result.add(method); + } + } + return result; + } + + public PseudoMethod findMethod(String name, String descriptor) { + for (PseudoMethod method : myMethods) { + if (method.getName().equals(name) && method.getSignature().equals(descriptor)){ + return method; + } + } + return null; + } + + public InstrumentationClassFinder getFinder() { + return InstrumentationClassFinder.this; } public PseudoClass getSuperClass() throws IOException, ClassNotFoundException { @@ -173,36 +287,69 @@ public class InstrumentationClassFinder { if (x.implementsInterface(this)) { return true; } - if (x.isInterface() && getName().equals("java/lang/Object")) { + if (x.isInterface() && "java/lang/Object".equals(getName())) { return true; } return false; } - public boolean isInterface() { - return isInterface; + public boolean hasDefaultPublicConstructor() { + for (PseudoMethod method : myMethods) { + if ("".equals(method.getName()) && "()V".equals(method.getSignature())) { + return true; + } + } + return false; + } + + public String getDescriptor() { + return "L" + myName + ";"; + } + } + + public static final class PseudoMethod { + private final int myAccess; + private final String myName; + private final String mySignature; + + public PseudoMethod(int access, String name, String signature) { + myAccess = access; + myName = name; + mySignature = signature; + } + + public int getModifiers() { + return myAccess; } public String getName() { return myName; } + + public String getSignature() { + return mySignature; + } } private static class V extends EmptyVisitor { public String mySuperclassName = null; public String[] myInterfaces = null; public String myName = null; - public boolean myIsInterface = false; + public int myModifiers; + private final List myMethods = new ArrayList(); - public void visitAttribute(Attribute attr) { - super.visitAttribute(attr); + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if ((access & Opcodes.ACC_PUBLIC) > 0) { + myMethods.add(new PseudoMethod(access, name, desc)); + } + return super.visitMethod(access, name, desc, signature, exceptions); } public void visit(int version, int access, String pName, String signature, String pSuperName, String[] pInterfaces) { mySuperclassName = pSuperName; myInterfaces = pInterfaces; myName = pName; - myIsInterface = (access & Opcodes.ACC_INTERFACE) > 0; + myModifiers = access; } } @@ -221,7 +368,6 @@ public class InstrumentationClassFinder { } } - @Nullable public Resource getResource(String s, boolean flag) { int i = 0; for (Loader loader; (loader = getLoader(i)) != null; i++) { @@ -242,7 +388,6 @@ public class InstrumentationClassFinder { myLoadersMap.clear(); } - @Nullable private synchronized Loader getLoader(int i) { while (myLoaders.size() < i + 1) { URL url; @@ -275,7 +420,6 @@ public class InstrumentationClassFinder { return myLoaders.get(i); } - @Nullable private Loader getLoader(final URL url, int index) throws IOException { String s; try { @@ -317,7 +461,6 @@ public class InstrumentationClassFinder { return myURL; } - @Nullable public abstract Resource getResource(final String name, boolean flag); public abstract void releaseResources(); @@ -345,7 +488,6 @@ public class InstrumentationClassFinder { public void releaseResources() { } - @Nullable public Resource getResource(final String name, boolean check) { URL url = null; File file = null; @@ -410,7 +552,6 @@ public class InstrumentationClassFinder { } } - @NonNls public String toString() { return "FileLoader [" + myRootDir + "]"; } @@ -438,7 +579,6 @@ public class InstrumentationClassFinder { } } - @Nullable private ZipFile acquireZipFile() throws IOException { ZipFile zipFile = myZipFile; if (zipFile == null) { @@ -448,7 +588,6 @@ public class InstrumentationClassFinder { return zipFile; } - @Nullable private ZipFile doGetZipFile() throws IOException { if (FILE_PROTOCOL.equals(myURL.getProtocol())) { String s = unescapePercentSequences(myURL.getFile().replace('/', File.separatorChar)); @@ -463,7 +602,6 @@ public class InstrumentationClassFinder { return null; } - @Nullable public Resource getResource(String name, boolean flag) { try { final ZipFile file = acquireZipFile(); @@ -501,11 +639,9 @@ public class InstrumentationClassFinder { return myURL; } - @Nullable public InputStream getInputStream() throws IOException { - ZipFile file = null; try { - file = acquireZipFile(); + final ZipFile file = acquireZipFile(); if (file == null) { return null; } @@ -527,7 +663,6 @@ public class InstrumentationClassFinder { } } - @NonNls public String toString() { return "JarLoader [" + myURL + "]"; } @@ -535,8 +670,7 @@ public class InstrumentationClassFinder { } - @NotNull - private static String unescapePercentSequences(@NotNull String s) { + private static String unescapePercentSequences(String s) { if (s.indexOf('%') == -1) { return s; } @@ -591,4 +725,27 @@ public class InstrumentationClassFinder { return -1; } + public byte[] loadBytes(InputStream stream) { + byte[] buf = myBuffer; + if (buf == null) { + buf = new byte[512]; + myBuffer = buf; + } + + final ByteArrayOutputStream result = new ByteArrayOutputStream(); + try { + while (true) { + int n = stream.read(buf, 0, buf.length); + if (n <= 0) { + break; + } + result.write(buf, 0, n); + } + result.close(); + } + catch (IOException ignored) { + } + return result.toByteArray(); + } + } diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java new file mode 100644 index 000000000000..ffdf058a2fbf --- /dev/null +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java @@ -0,0 +1,43 @@ +package com.intellij.compiler.instrumentation; + +import org.objectweb.asm.ClassWriter; + +/** +* @author Eugene Zhuravlev +* Date: 3/27/12 +*/ +public class InstrumenterClassWriter extends ClassWriter { + private final InstrumentationClassFinder myFinder; + + public InstrumenterClassWriter(int flags, final InstrumentationClassFinder finder) { + super(flags); + myFinder = finder; + } + + protected String getCommonSuperClass(final String type1, final String type2) { + try { + final InstrumentationClassFinder.PseudoClass cls1 = myFinder.loadClass(type1); + final InstrumentationClassFinder.PseudoClass cls2 = myFinder.loadClass(type2); + if (cls1.isAssignableFrom(cls2)) { + return cls1.getName(); + } + if (cls2.isAssignableFrom(cls1)) { + return cls2.getName(); + } + if (cls1.isInterface() || cls2.isInterface()) { + return "java/lang/Object"; + } + else { + InstrumentationClassFinder.PseudoClass c = cls1; + do { + c = c.getSuperClass(); + } + while (!c.isAssignableFrom(cls2)); + return c.getName(); + } + } + catch (Exception e) { + throw new RuntimeException(e.toString(), e); + } + } +} diff --git a/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java similarity index 100% rename from java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java rename to java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java diff --git a/java/compiler/javac2/javac2.iml b/java/compiler/javac2/javac2.iml index 49c3fa54efee..a8680af11500 100644 --- a/java/compiler/javac2/javac2.iml +++ b/java/compiler/javac2/javac2.iml @@ -11,7 +11,7 @@ - + diff --git a/java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java b/java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java deleted file mode 100644 index dc8b6552147d..000000000000 --- a/java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java +++ /dev/null @@ -1,54 +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.ant; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; - -import java.io.IOException; - -/** - * @author yole - */ -public class AntClassWriter extends ClassWriter { - private final PseudoClassLoader myPseudoClassLoader; - - public AntClassWriter(int flags, final PseudoClassLoader pseudoLoader) { - super(flags); - myPseudoClassLoader = pseudoLoader; - } - - public AntClassWriter(ClassReader classReader, int flags, final PseudoClassLoader pseudoLoader) { - super(classReader, flags); - myPseudoClassLoader = pseudoLoader; - } - - protected String getCommonSuperClass(final String type1, final String type2) { - try { - PseudoClassLoader.PseudoClass p1 = myPseudoClassLoader.loadClass(type1); - PseudoClassLoader.PseudoClass p2 = myPseudoClassLoader.loadClass(type2); - - return p1.getCommonSuperClassName(p2); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - } -} diff --git a/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java b/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java index 8409618031a9..eb423ae59820 100644 --- a/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java +++ b/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java @@ -15,6 +15,8 @@ */ package com.intellij.ant; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.uiDesigner.compiler.*; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; @@ -39,14 +41,14 @@ import java.util.*; */ public class InstrumentationUtil { - public static PseudoClassLoader createPseudoClassLoader(final String classPath) throws MalformedURLException { + public static InstrumentationClassFinder createInstrumentationClassFinder(final String classPath) throws MalformedURLException { final ArrayList urls = new ArrayList(); for (StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer.hasMoreTokens();) { final String s = tokenizer.nextToken(); urls.add(new File(s).toURL()); } final URL[] urlsArr = (URL[])urls.toArray(new URL[urls.size()]); - return new PseudoClassLoader(urlsArr); + return new InstrumentationClassFinder(urlsArr); } public static int getClassFileVersion(ClassReader reader) { @@ -108,12 +110,12 @@ public class InstrumentationUtil { } private class AntNestedFormLoader implements NestedFormLoader { - private final PseudoClassLoader myLoader; + private final InstrumentationClassFinder myClassFinder; private final List myNestedFormPathList; private final HashMap myFormCache = new HashMap(); - public AntNestedFormLoader(final PseudoClassLoader loader, List nestedFormPathList) { - myLoader = loader; + public AntNestedFormLoader(final InstrumentationClassFinder classFinder, List nestedFormPathList) { + myClassFinder = classFinder; myNestedFormPathList = nestedFormPathList; } @@ -143,7 +145,7 @@ public class InstrumentationUtil { } } } - InputStream resourceStream = myLoader.getLoader ().getResourceAsStream(formFilePath); + InputStream resourceStream = myClassFinder.getResourceAsStream(formFilePath); if (resourceStream != null) { return loadForm(formFilePath, resourceStream); } @@ -164,11 +166,11 @@ public class InstrumentationUtil { } } - public void instrumentForm(final File file, final PseudoClassLoader loader) { + public void instrumentForm(final File file, final InstrumentationClassFinder classFinder) { log("compiling form " + file.getAbsolutePath(), Project.MSG_VERBOSE); final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(file.toURL(), new CompiledClassPropertiesProvider(loader.getLoader ())); + rootContainer = Utils.getRootContainer(file.toURL(), new CompiledClassPropertiesProvider(classFinder.getLoader())); } catch (AlienFormFileException e) { // ignore non-IDEA forms @@ -216,9 +218,9 @@ public class InstrumentationUtil { finally { stream.close(); } - AntNestedFormLoader formLoader = new AntNestedFormLoader(loader, myNestedFormPathList); - AntClassWriter classWriter = new AntClassWriter(InstrumentationUtil.getAsmClassWriterFlags(version), loader); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader.getLoader(), formLoader, false, classWriter); + AntNestedFormLoader formLoader = new AntNestedFormLoader(classFinder, myNestedFormPathList); + InstrumenterClassWriter classWriter = new InstrumenterClassWriter(InstrumentationUtil.getAsmClassWriterFlags(version), classFinder); + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, classFinder, formLoader, false, classWriter); codeGenerator.patchFile(classFile); final FormErrorInfo[] warnings = codeGenerator.getWarnings(); @@ -243,15 +245,15 @@ public class InstrumentationUtil { } } - public static byte[] instrumentNotNull(final byte[] buffer, final PseudoClassLoader loader) { + public static byte[] instrumentNotNull(final byte[] buffer, final InstrumentationClassFinder loader) { return instrumentNotNull(new ClassReader (buffer), loader); } - private static byte[] instrumentNotNull(final ClassReader reader, final PseudoClassLoader loader) { + private static byte[] instrumentNotNull(final ClassReader reader, final InstrumentationClassFinder loader) { int version = getClassFileVersion(reader); if (version >= Opcodes.V1_5) { - ClassWriter writer = new AntClassWriter(getAsmClassWriterFlags(version), loader); + ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), loader); final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer); reader.accept(instrumenter, 0); @@ -264,7 +266,7 @@ public class InstrumentationUtil { return null; } - public static int instrumentNotNull(final File file, final PseudoClassLoader loader) throws IOException { + public static int instrumentNotNull(final File file, final InstrumentationClassFinder loader) throws IOException { int instrumented = 0; final String path = file.getPath(); final FileInputStream inputStream = new FileInputStream(file); diff --git a/java/compiler/javac2/src/com/intellij/ant/Javac2.java b/java/compiler/javac2/src/com/intellij/ant/Javac2.java index be4354258ac8..5c3035534b44 100644 --- a/java/compiler/javac2/src/com/intellij/ant/Javac2.java +++ b/java/compiler/javac2/src/com/intellij/ant/Javac2.java @@ -15,6 +15,8 @@ */ package com.intellij.ant; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.uiDesigner.compiler.*; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; @@ -201,26 +203,34 @@ public class Javac2 extends Javac { * class files. */ protected void compile() { - // compile java - if (areJavaClassesCompiled()) { - super.compile(); - } + // compile java + if (areJavaClassesCompiled()) { + super.compile(); + } - PseudoClassLoader loader = buildClasspathClassLoader(); - if (loader == null) return; - instrumentForms(loader); + InstrumentationClassFinder finder = buildClasspathClassLoader(); + if (finder == null) { + return; + } + try { + instrumentForms(finder); //NotNull instrumentation - final int instrumented = instrumentNotNull(getDestdir(), loader); + final int instrumented = instrumentNotNull(getDestdir(), finder); + log("Added @NotNull assertions to " + instrumented + " files", Project.MSG_INFO); + } + finally { + finder.releaseResources(); + } } - /** + /** * Instrument forms * - * @param loader a classloader to use + * @param finder a classloader to use */ - private void instrumentForms(final PseudoClassLoader loader) { + private void instrumentForms(final InstrumentationClassFinder finder) { // we instrument every file, because we cannot find which files should not be instrumented without dependency storage final ArrayList formsToInstrument = myFormFiles; @@ -237,7 +247,7 @@ public class Javac2 extends Javac { log("compiling form " + formFile.getAbsolutePath(), Project.MSG_VERBOSE); final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(formFile.toURL(), new CompiledClassPropertiesProvider(loader.getLoader())); + rootContainer = Utils.getRootContainer(formFile.toURL(), new CompiledClassPropertiesProvider(finder.getLoader())); } catch (AlienFormFileException e) { // ignore non-IDEA forms @@ -283,9 +293,9 @@ public class Javac2 extends Javac { finally { stream.close(); } - AntNestedFormLoader formLoader = new AntNestedFormLoader(loader.getLoader(), myNestedFormPathList); - AntClassWriter classWriter = new AntClassWriter(getAsmClassWriterFlags(version), loader); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader.getLoader(), formLoader, false, classWriter); + AntNestedFormLoader formLoader = new AntNestedFormLoader(finder.getLoader(), myNestedFormPathList); + InstrumenterClassWriter classWriter = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, formLoader, false, classWriter); codeGenerator.patchFile(classFile); final FormErrorInfo[] warnings = codeGenerator.getWarnings(); @@ -322,7 +332,7 @@ public class Javac2 extends Javac { * * @return a URL classloader */ - private PseudoClassLoader buildClasspathClassLoader() { + private InstrumentationClassFinder buildClasspathClassLoader() { final StringBuffer classPathBuffer = new StringBuffer(); final Path cp = new Path(getProject()); appendPath(cp, getBootclasspath()); @@ -349,7 +359,7 @@ public class Javac2 extends Javac { log("classpath=" + classPath, Project.MSG_VERBOSE); try { - return InstrumentationUtil.createPseudoClassLoader(classPath); + return InstrumentationUtil.createInstrumentationClassFinder(classPath); } catch (MalformedURLException e) { fireError(e.getMessage()); @@ -373,10 +383,10 @@ public class Javac2 extends Javac { * Instrument classes with NotNull annotations * * @param dir the directory with classes to instrument (the directory is processed recursively) - * @param loader the classloader to use + * @param finder the classloader to use * @return the amount of classes actually affected by instrumentation */ - private int instrumentNotNull(File dir, final PseudoClassLoader loader) { + private int instrumentNotNull(File dir, final InstrumentationClassFinder finder) { int instrumented = 0; final File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { @@ -393,7 +403,7 @@ public class Javac2 extends Javac { int version = getClassFileVersion(reader); if (version >= Opcodes.V1_5) { - ClassWriter writer = new AntClassWriter(getAsmClassWriterFlags(version), loader); + ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer); reader.accept(instrumenter, 0); @@ -421,7 +431,7 @@ public class Javac2 extends Javac { } } else if (file.isDirectory()) { - instrumented += instrumentNotNull(file, loader); + instrumented += instrumentNotNull(file, finder); } } diff --git a/java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java b/java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java deleted file mode 100644 index 97a4172d7b94..000000000000 --- a/java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2000-2011 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.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.commons.EmptyVisitor; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * @author db - * Date: 06.06.11 - */ -public class PseudoClassLoader { - static final WeakHashMap myCache = new WeakHashMap(); - - final Map myDefinedClasses = new HashMap (); - final Map myDefinedClassesData = new HashMap (); - - private class MemoryClassLoader extends ClassLoader { - public MemoryClassLoader(URLClassLoader classpathLoader) { - super(classpathLoader); - } - - protected Class findClass(String name) throws ClassNotFoundException { - final byte[] data = (byte[])myDefinedClassesData.get(name); - if (data == null) { - throw new ClassNotFoundException(name); - } - return defineClass(name, data, 0, data.length); - } - - public URL findResource(String name) { - return super.findResource(name); - } - } - - public class PseudoClass { - final String myName; - final String mySuperClass; - final String[] myInterfaces; - final boolean isInterface; - - private PseudoClass(final Class repr) { - final Class superclass = repr.getSuperclass(); - final Class[] interfaces = repr.getInterfaces(); - - myName = repr.getName().replace('.', '/'); - mySuperClass = superclass == null ? null : superclass.getName().replace('.', '/'); - myInterfaces = interfaces.length == 0 ? null : new String[interfaces.length]; - - for (int i=0; i 0; - } - } - - private PseudoClass createPseudoClass(final ClassReader r) { - final V visitor = new V(); - - r.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - - return new PseudoClass(visitor.name, visitor.superName, visitor.interfaces, visitor.isInterface); - } - - private class Tag { - final PseudoClass myClass; - final long myStamp; - - private Tag(PseudoClass aClass, long stamp) { - myClass = aClass; - myStamp = stamp; - } - } - - public PseudoClass loadClass(final String internalName) throws IOException, ClassNotFoundException { - final PseudoClass defined = (PseudoClass) myDefinedClasses.get(internalName); - - if (defined != null) { - return defined; - } - - final URL resource = myLoader.findResource(internalName + ".class"); - - if (resource == null) { - final Class lastResort = myLoader.loadClass(internalName.replace('/', '.')); - return new PseudoClass(lastResort); - } - - final String fileName = resource.getFile(); - final boolean isFile = fileName.length() > 0; - final File file = new File(fileName); - - if (isFile) { - final Tag cached = (Tag)myCache.get(internalName); - - if (cached != null && cached.myStamp == file.lastModified()) { - return cached.myClass; - } - } - - final InputStream content = (InputStream)resource.getContent(); - final ClassReader reader = new ClassReader(content); - final PseudoClass result = createPseudoClass(reader); - - if (isFile) { - myCache.put(internalName, new Tag(result, file.lastModified())); - } - - return result; - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java index 3cfdb3a8979f..f2459aadff39 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java @@ -32,20 +32,13 @@ import com.sun.jdi.ReferenceType; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author lex */ class ReloadClassesWorker { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.ReloadClassesWorker"); - /** - * number of clasess that will be reloaded in one go. - * Such restriction is needed to deal with big number of classes being reloaded - */ - private static final int CLASSES_CHUNK_SIZE = 100; private final DebuggerSession myDebuggerSession; private final HotSwapProgress myProgress; @@ -111,11 +104,12 @@ class ReloadClassesWorker { final Project project = debugProcess.getProject(); final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager(); breakpointManager.disableBreakpoints(debugProcess); - + //virtualMachineProxy.suspend(); - + try { - final Map redefineMap = new HashMap(); + RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy); + int processedClassesCount = 0; for (final String qualifiedName : modifiedClasses.keySet()) { processedClassesCount++; @@ -124,32 +118,30 @@ class ReloadClassesWorker { myProgress.setFraction(processedClassesCount / (double)modifiedClasses.size()); } final HotSwapFile fileDescr = modifiedClasses.get(qualifiedName); + final byte[] content; try { - final byte[] buffer = FileUtil.loadFileBytes(fileDescr.file); - final List classes = virtualMachineProxy.classesByName(qualifiedName); - for (final ReferenceType reference : classes) { - redefineMap.put(reference, buffer); - } + content = FileUtil.loadFileBytes(fileDescr.file); } catch (IOException e) { reportProblem(qualifiedName, e); + continue; } - if (redefineMap.size() >= CLASSES_CHUNK_SIZE) { - // reload this portion of clasess and clear the map to free memory - try { - virtualMachineProxy.redefineClasses(redefineMap); - } - finally { - redefineMap.clear(); - } - } - } - if (redefineMap.size() > 0) { - virtualMachineProxy.redefineClasses(redefineMap); + redefineProcessor.processClass(qualifiedName, content); } + redefineProcessor.processPending(); myProgress.setFraction(1); - - myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.classes.reloaded", modifiedClasses.size())); + + final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount(); + if (partiallyRedefinedClassesCount == 0) { + myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, + DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount())); + } + else { + final String message = DebuggerBundle.message("status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount, + redefineProcessor.getProcessedClassesCount()); + myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message); + } + if (LOG.isDebugEnabled()) { LOG.debug("classes reloaded"); } @@ -203,11 +195,10 @@ class ReloadClassesWorker { catch (Exception e) { processException(e); } - } private void reportProblem(final String qualifiedName, @Nullable Exception ex) { - String reason = null; + String reason = null; if (ex != null) { reason = ex.getLocalizedMessage(); } @@ -223,4 +214,78 @@ class ReloadClassesWorker { StringBuilderSpinAllocator.dispose(buf); } } + + private static class RedefineProcessor { + /** + * number of classes that will be reloaded in one go. + * Such restriction is needed to deal with big number of classes being reloaded + */ + private static final int CLASSES_CHUNK_SIZE = 100; + private final VirtualMachineProxyImpl myVirtualMachineProxy; + private final Map myRedefineMap = new HashMap(); + private int myProcessedClassesCount; + private int myPartiallyRedefinedClassesCount; + + public RedefineProcessor(VirtualMachineProxyImpl virtualMachineProxy) { + myVirtualMachineProxy = virtualMachineProxy; + } + + public void processClass(String qualifiedName, byte[] content) throws Throwable { + final List vmClasses = myVirtualMachineProxy.classesByName(qualifiedName); + if (vmClasses.isEmpty()) return; + + if (vmClasses.size() == 1) { + myRedefineMap.put(vmClasses.get(0), content); + if (myRedefineMap.size() >= CLASSES_CHUNK_SIZE) { + processChunk(); + } + return; + } + + int redefinedVersionsCount = 0; + Throwable error = null; + for (ReferenceType vmClass : vmClasses) { + try { + myVirtualMachineProxy.redefineClasses(Collections.singletonMap(vmClass, content)); + redefinedVersionsCount++; + } + catch (Throwable t) { + error = t; + } + } + if (redefinedVersionsCount == 0) { + throw error; + } + + if (redefinedVersionsCount < vmClasses.size()) { + myPartiallyRedefinedClassesCount++; + } + myProcessedClassesCount++; + } + + private void processChunk() throws Throwable { + // reload this portion of classes and clear the map to free memory + try { + myVirtualMachineProxy.redefineClasses(myRedefineMap); + myProcessedClassesCount += myRedefineMap.size(); + } + finally { + myRedefineMap.clear(); + } + } + + public void processPending() throws Throwable { + if (myRedefineMap.size() > 0) { + processChunk(); + } + } + + public int getProcessedClassesCount() { + return myProcessedClassesCount; + } + + public int getPartiallyRedefinedClassesCount() { + return myPartiallyRedefinedClassesCount; + } + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java index 74f8c0882532..e4e49aa18b0e 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java @@ -80,6 +80,7 @@ public class PackagingElementNode> extends Artifac return myPackagingElements.size() == 1 ? myPackagingElements.get(0) : null; } + @NotNull @Override public Object[] getEqualityObjects() { return ArrayUtil.toObjectArray(myPackagingElements); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java index 35dcd13d1c2d..3abe7671318a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java @@ -20,6 +20,7 @@ import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactEditorEx; import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingSourceItem; import com.intellij.ui.treeStructure.SimpleTree; +import org.jetbrains.annotations.NotNull; import java.awt.event.InputEvent; import java.util.Collections; @@ -35,6 +36,7 @@ public class SourceItemNode extends SourceItemNodeBase { mySourceItem = sourceItem; } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[]{mySourceItem}; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java index c094f3caa5bc..fa83689521e5 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java @@ -35,6 +35,7 @@ public class SourceItemsTreeRoot extends SourceItemNodeBase { return null; } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[]{"root"}; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java index 4a6ea36e7de0..be3f59f985d2 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java @@ -27,6 +27,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.OrderRootType; @@ -371,7 +372,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } } - public abstract class AttachItemActionBase extends AnAction { + public abstract class AttachItemActionBase extends DumbAwareAction { private VirtualFile myLastChosen = null; protected AttachItemActionBase(String text) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java index 7d1e7c43b49f..b63cc1e5592e 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java @@ -290,6 +290,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable { return myElement.equals(other.myElement) && (!other.myCheck || myCheck) && (!other.myCollectUsages || myCollectUsages); } + @NotNull @Override public Object[] getEqualityObjects() { return myEqualityObjects; diff --git a/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java b/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java index 2598cc730981..97649e847afb 100644 --- a/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java +++ b/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java @@ -269,6 +269,7 @@ public abstract class ChooseLibrariesDialogBase extends DialogWrapper { return 0; } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myElement}; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java index 3f43a51568b0..c06a82b1062f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java @@ -66,7 +66,7 @@ public class SuppressAllForClassFix extends SuppressFix { } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiDocCommentOwner container = getContainer(element); LOG.assertTrue(container != null); if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java index 2c5cd77301aa..a8464dc6c9c8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java @@ -105,7 +105,7 @@ public class SuppressFix extends SuppressIntentionAction { } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { PsiDocCommentOwner container = getContainer(element); assert container != null; if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java index dbd6e2f38cc0..49682f21e312 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java @@ -66,7 +66,7 @@ public class SuppressParameterFix extends SuppressIntentionAction { } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { PsiParameter container = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false); assert container != null; if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 4a0ed7347583..d2a350e0d918 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -26,6 +26,8 @@ import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaSdkVersionUtil; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; @@ -505,7 +507,17 @@ public class GenericsHighlightUtil { final PsiType retErasure1 = TypeConversionUtil.erasure(checkMethod.getReturnType()); final PsiType retErasure2 = TypeConversionUtil.erasure(superMethod.getReturnType()); - if (!Comparing.equal(retErasure1, retErasure2) && + + boolean differentReturnTypeErasure = !Comparing.equal(retErasure1, retErasure2); + if (checkEqualsSuper && JavaSdkVersionUtil.isAtLeast(checkMethod, JavaSdkVersion.JDK_1_7)) { + if (retErasure1 != null && retErasure2 != null) { + differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2); + } else { + differentReturnTypeErasure = !(retErasure1 == null && retErasure2 == null); + } + } + + if (differentReturnTypeErasure && !TypeConversionUtil.isVoidType(retErasure1) && !TypeConversionUtil.isVoidType(retErasure2) && !(checkEqualsSuper && Arrays.equals(superSignature.getParameterTypes(), signatureToCheck.getParameterTypes()))) { @@ -676,7 +688,7 @@ public class GenericsHighlightUtil { return true; } } - if (isUncheckedTypeArgumentConversion(lTypeArg, rTypeArg)) return true; + if (!TypeConversionUtil.typesAgree(lTypeArg, rTypeArg, false)) return true; } return false; } @@ -718,48 +730,6 @@ public class GenericsHighlightUtil { return false; } - private static boolean isUncheckedTypeArgumentConversion (PsiType lTypeArg, PsiType rTypeArg) { - if (lTypeArg instanceof PsiPrimitiveType || rTypeArg instanceof PsiPrimitiveType) return false; - if (lTypeArg.equals(rTypeArg)) return false; - if (lTypeArg instanceof PsiCapturedWildcardType) { - //ignore capture conversion - return isUncheckedTypeArgumentConversion(((PsiCapturedWildcardType)lTypeArg).getWildcard(), rTypeArg); - } - if (rTypeArg instanceof PsiCapturedWildcardType) { - //ignore capture conversion - return isUncheckedTypeArgumentConversion(lTypeArg, ((PsiCapturedWildcardType)rTypeArg).getWildcard()); - } - - if (lTypeArg instanceof PsiWildcardType || rTypeArg instanceof PsiWildcardType) { - return !lTypeArg.isAssignableFrom(rTypeArg); - } - - if (lTypeArg instanceof PsiArrayType && rTypeArg instanceof PsiArrayType) { - return isUncheckedTypeArgumentConversion(((PsiArrayType)rTypeArg).getComponentType(), ((PsiArrayType)lTypeArg).getComponentType()); - } - if (lTypeArg instanceof PsiArrayType || rTypeArg instanceof PsiArrayType) return false; - if (lTypeArg instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)lTypeArg).getConjuncts()) { - if (!isUncheckedTypeArgumentConversion(type, rTypeArg)) return false; - } - return true; - } - if (!(lTypeArg instanceof PsiClassType)) { - LOG.error("left: "+lTypeArg + "; "+lTypeArg.getClass()); - } - if (rTypeArg instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)rTypeArg).getConjuncts()) { - if (!isUncheckedTypeArgumentConversion(lTypeArg, type)) return false; - } - return true; - } - if (!(rTypeArg instanceof PsiClassType)) { - LOG.error("right :"+rTypeArg + "; "+rTypeArg.getClass()); - } - return ((PsiClassType)lTypeArg).resolve() instanceof PsiTypeParameter || - ((PsiClassType)rTypeArg).resolve() instanceof PsiTypeParameter; - } - @Nullable public static HighlightInfo checkForeachLoopParameterType(PsiForeachStatement statement) { final PsiParameter parameter = statement.getIterationParameter(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java index dc09b28a11e4..4348764edd35 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java @@ -83,7 +83,7 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); final PsiMethod method = (PsiMethod)parameter.getDeclarationScope(); final PsiMethod prototype = (PsiMethod)method.getContainingClass().addBefore(generateMethodPrototype(method, parameter), method); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java index 514d5f78efaf..74ab0409705a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java @@ -112,7 +112,9 @@ public class IterateOverIterableIntention implements IntentionAction { element = ((PsiExpressionStatement)element).getExpression().getLastChild(); } while ((element = PsiTreeUtil.getParentOfType(element, PsiExpression.class, true)) != null) { - if (element.getParent() instanceof PsiMethodCallExpression) continue; + final PsiElement parent = element.getParent(); + if (parent instanceof PsiMethodCallExpression) continue; + if (!(parent instanceof PsiExpressionStatement)) return null; final PsiType type = ((PsiExpression)element).getType(); if (type instanceof PsiArrayType || InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE)) return (PsiExpression)element; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java index ff23c5fcaa12..a5cfce5dd068 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java @@ -66,7 +66,7 @@ public class QualifyThisArgumentFix extends PsiElementBaseIntentionAction { } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { myExpression.replace(RefactoringUtil.createThisExpression(PsiManager.getInstance(project), myPsiClass)); } diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java index 34305ef9bc58..6c1f9220644d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.folding.impl; +import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil; import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.lang.ASTNode; @@ -47,7 +48,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAware { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.folding.impl.JavaFoldingBuilder"); @@ -312,7 +316,9 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar if (importKeyword == null) return null; int startOffset = importKeyword.getTextRange().getEndOffset() + 1; int endOffset = statements[statements.length - 1].getTextRange().getEndOffset(); - return new TextRange(startOffset, endOffset); + if (!hasErrorElementsNearby(element.getContainingFile(), startOffset, endOffset)) { + return new TextRange(startOffset, endOffset); + } } if (element instanceof PsiDocComment) { return element.getTextRange(); @@ -330,6 +336,16 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar return null; } + public static boolean hasErrorElementsNearby(final PsiFile file, int startOffset, int endOffset) { + endOffset = CharArrayUtil.shiftForward(file.getText(), endOffset, " \t\n"); + for (PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffset, endOffset)) { + if (element instanceof PsiErrorElement) { + return true; + } + } + return false; + } + @Nullable private static TextRange getFileHeader(PsiJavaFile file) { PsiElement first = file.getFirstChild(); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java index 281a18d78abc..0681808cea69 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java @@ -46,7 +46,7 @@ public class InsertLiteralUnderscoresAction extends PsiElementBaseIntentionActio } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(element, PsiLiteralExpression.class, false); if (literalExpression == null) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java index 4207625a54ca..320104e934de 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java @@ -40,7 +40,7 @@ public class RemoveLiteralUnderscoresAction extends PsiElementBaseIntentionActio } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(element, PsiLiteralExpression.class, false); if (literalExpression == null) return; diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java index ee8959c4efab..e9963add3b43 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java @@ -5,7 +5,6 @@ package com.intellij.codeInspection.javaDoc; import com.intellij.ExtensionPoints; import com.intellij.codeInsight.CodeInsightUtil; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; @@ -1176,7 +1175,6 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); //correct save settings - ((ModifiableModel)inspectionProfile).isProperSetting(HighlightDisplayKey.find(SHORT_NAME)); InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile); //TODO lesya diff --git a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java index 2d89664d9568..e1ce6732f694 100644 --- a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java +++ b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java @@ -16,14 +16,11 @@ package com.intellij.codeInspection.util; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; import com.intellij.ide.DataManager; import com.intellij.ide.util.ClassFilter; import com.intellij.ide.util.TreeClassChooser; @@ -209,7 +206,6 @@ public class SpecialAnnotationsUtil { Collections.sort(targetList); final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); //correct save settings - ((InspectionProfileImpl)inspectionProfile).isProperSetting(HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME)); //TODO lesya InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile); diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java new file mode 100644 index 000000000000..366a0b870404 --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.projectRoots; + +import com.intellij.psi.PsiElement; + +/** + * User: anna + * Date: 3/28/12 + */ +public class JavaVersionServiceImpl extends JavaVersionService { + @Override + public boolean isAtLeast(PsiElement element, JavaSdkVersion version) { + return JavaSdkVersionUtil.isAtLeast(element, version); + } +} diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index ace9c134e0a7..005be2d1bd4f 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.projectRoots.impl; +import com.intellij.execution.util.ExecUtil; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.*; @@ -154,33 +155,27 @@ public class JavaSdkImpl extends JavaSdk { public String suggestHomePath() { if (SystemInfo.isMac) { if (new File("/usr/libexec/java_home").exists()) { - try { - final Process exec = Runtime.getRuntime().exec("/usr/libexec/java_home"); - final BufferedReader input = new BufferedReader(new InputStreamReader(exec.getInputStream())); - try { - final String path = input.readLine(); - if (new File(path).exists()) return path; - } - finally { - input.close(); - } + final String path = ExecUtil.execAndReadLine("/usr/libexec/java_home"); + if (path != null && new File(path).exists()) { + return path; } - catch (IOException ignore) { } } - - return "/System/Library/Frameworks/JavaVM.framework/Versions/"; + return "/System/Library/Frameworks/JavaVM.framework/Versions"; } + if (SystemInfo.isLinux) { - final String[] homes = {"/usr/java", "/opt/java", "/usr/lib/jvm/"}; + final String[] homes = {"/usr/java", "/opt/java", "/usr/lib/jvm"}; for (String home : homes) { if (new File(home).isDirectory()) { return home; } } } + if (SystemInfo.isSolaris) { - return "/usr/jdk/"; + return "/usr/jdk"; } + return null; } diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java index 5d06e931eab2..d960ac43f833 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java @@ -192,10 +192,14 @@ public class PullUpDialog extends RefactoringDialog { protected void doAction() { if (!myCallback.checkConflicts(this)) return; JavaRefactoringSettings.getInstance().PULL_UP_MEMBERS_JAVADOC = myJavaDocPanel.getPolicy(); - StatisticsManager - .getInstance().incUseCount(new StatisticsInfo(PULL_UP_STATISTICS_KEY + myClass.getQualifiedName(), getSuperClass().getQualifiedName())); + final PsiClass superClass = getSuperClass(); + String name = superClass.getQualifiedName(); + if (name != null) { + StatisticsManager + .getInstance().incUseCount(new StatisticsInfo(PULL_UP_STATISTICS_KEY + myClass.getQualifiedName(), name)); + } - invokeRefactoring(new PullUpHelper(myClass, getSuperClass(), getSelectedMemberInfos(), + invokeRefactoring(new PullUpHelper(myClass, superClass, getSelectedMemberInfos(), new DocCommentPolicy(getJavaDocPolicy()))); close(OK_EXIT_CODE); } diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java index cbb81cdc07ac..d5f6b4414ff3 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java @@ -22,6 +22,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchScopeUtil; import com.intellij.psi.search.searches.ReferencesSearch; @@ -241,7 +242,8 @@ public class RefactoringConflictsUtil { if (resolved != null && !reported.contains(resolved) && !CommonRefactoringUtil.isAncestor(resolved, scopes) && - !PsiSearchScopeUtil.isInScope(resolveScope, resolved)) { + !PsiSearchScopeUtil.isInScope(resolveScope, resolved) && + !(resolved instanceof LightElement)) { final String scopeDescription = RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(reference), true); final String message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.in.module.2", RefactoringUIUtil.getDescription(resolved, true), diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java index fda1ea726c1e..c46864483270 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java @@ -25,6 +25,7 @@ package com.intellij.refactoring.util; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; @@ -129,7 +130,13 @@ public class RefactoringHierarchyUtil { Collections.sort( basesList, new Comparator() { public int compare(PsiClass c1, PsiClass c2) { - return c1.getQualifiedName().compareTo(c2.getQualifiedName()); + final String fqn1 = c1.getQualifiedName(); + final String fqn2 = c2.getQualifiedName(); + if (fqn1 != null && fqn2 != null) return fqn1.compareTo(fqn2); + if (fqn1 == null && fqn2 == null) { + return Comparing.compare(c1.getName(), c2.getName()); + } + return fqn1 == null ? 1 : -1; } } ); diff --git a/java/java-impl/src/com/intellij/slicer/SliceNode.java b/java/java-impl/src/com/intellij/slicer/SliceNode.java index 7247b7f0e31b..df114e5f9751 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceNode.java +++ b/java/java-impl/src/com/intellij/slicer/SliceNode.java @@ -144,6 +144,7 @@ public class SliceNode extends AbstractTreeNode implements Duplicate @Override protected PresentationData createPresentation() { return new PresentationData(){ + @NotNull @Override public Object[] getEqualityObjects() { return ArrayUtil.append(super.getEqualityObjects(), changed); diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java similarity index 99% rename from java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java rename to java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 57a56966449f..8d3ff5daaf60 100644 --- a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -70,4 +70,5 @@ public enum JavaSdkVersion { String.format("Can't map Java SDK by description (%s). Available values: %s", description, Arrays.toString(values())) ); } + } diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java new file mode 100644 index 000000000000..b1573f95da60 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @author max + */ +package com.intellij.openapi.projectRoots; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiUtil; + +public class JavaVersionService { + public static JavaVersionService getInstance() { + return ServiceManager.getService(JavaVersionService.class); + } + + public boolean isAtLeast(PsiElement element, JavaSdkVersion version) { + return PsiUtil.getLanguageLevel(element).isAtLeast(version.getMaxLanguageLevel()); + } +} \ No newline at end of file diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 2abb12f5f1c4..557c12198331 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -354,7 +354,7 @@ public class TypeConversionUtil { final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1); if (class1 instanceof PsiTypeParameter) { for (PsiType type : class1.getExtendsListTypes()) { - if (TypesDistinctProver.provablyDistinct(type, typeArg2)) return false; + if (TypesDistinctProver.provablyDistinct(type, typeArg2) && !isAssignable(type, typeArg2)) return false; } } } @@ -656,10 +656,10 @@ public class TypeConversionUtil { } if (left instanceof PsiCapturedWildcardType) { - return left.equals(right) || isAssignable(((PsiCapturedWildcardType)left).getLowerBound(), right, allowUncheckedConversion); + return left.equals(right) || isAssignable(((PsiCapturedWildcardType)left).getLowerBound(), right, false); } if (right instanceof PsiCapturedWildcardType) { - return isAssignable(left, ((PsiCapturedWildcardType)right).getUpperBound(), allowUncheckedConversion); + return isAssignable(left, ((PsiCapturedWildcardType)right).getUpperBound(), false); } if (left instanceof PsiWildcardType) { @@ -746,7 +746,7 @@ public class TypeConversionUtil { private static boolean isAssignableToWildcard(PsiWildcardType wildcardType, PsiType right) { if (wildcardType.isSuper()) { - return isAssignable(right, wildcardType.getSuperBound()); + return isAssignable(wildcardType.getSuperBound(), right); } return isAssignable(wildcardType.getExtendsBound(), right); } @@ -859,7 +859,7 @@ public class TypeConversionUtil { return true; } - private static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) { + public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) { if (typeLeft instanceof PsiWildcardType) { final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft; final PsiType leftBound = leftWildcard.getBound(); diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java index 4f86a7039399..4f479fc41c7f 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java @@ -92,7 +92,10 @@ public class TypesDistinctProver { for (PsiClassType type : parameter.getExtendsListTypes()) { if (!TypeConversionUtil.isAssignable(type, substitutedType1 != null ? substitutedType1 : substitutedType2, false)) return true; } - } else if (provablyDistinct(substitutedType1, substitutedType2)) return true; + } else { + if (provablyDistinct(substitutedType1, substitutedType2)) return true; + if (substitutedType1 instanceof PsiWildcardType && !((PsiWildcardType)substitutedType1).isBounded()) return true; + } } return false; } @@ -100,8 +103,8 @@ public class TypesDistinctProver { final PsiClass boundClass1 = classResolveResult1.getElement(); final PsiClass boundClass2 = classResolveResult2.getElement(); return type2 != null && type1 != null && !type1.equals(type2) && - !InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) && - !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true); + (!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) || + !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true)); } public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2) { diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java index 6c2a98db24b7..d6f0e06de710 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java @@ -24,6 +24,8 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.lang.java.JavaParserDefinition; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.vfs.VirtualFile; @@ -86,6 +88,7 @@ public class JavaCoreEnvironment extends CoreEnvironment { myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl()); myApplication.registerService(JavaDirectoryService.class, new CoreJavaDirectoryService()); + myApplication.registerService(JavaVersionService.class, new JavaVersionService()); } public void addToClasspath(File path) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index df49e326cf5e..9d927c6832a4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -19,6 +19,8 @@ */ package com.intellij.psi.impl.source.resolve; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.javadoc.PsiDocComment; @@ -160,15 +162,20 @@ public class JavaResolveUtil { private static PsiClass getTopLevelClass(@NotNull PsiElement place, PsiClass memberClass) { PsiClass lastClass = null; + Boolean isAtLeast17 = null; for (PsiElement placeParent = place; placeParent != null; placeParent = placeParent.getContext()) { - if (placeParent instanceof PsiClass && - !(placeParent instanceof PsiAnonymousClass) && - !(placeParent instanceof PsiTypeParameter)) { - PsiClass aClass = (PsiClass)placeParent; - - if (memberClass != null && aClass.isInheritor(memberClass, true)) return aClass; - - lastClass = aClass; + if (placeParent instanceof PsiClass && !(placeParent instanceof PsiAnonymousClass)) { + final boolean isTypeParameter = placeParent instanceof PsiTypeParameter; + if (isTypeParameter && isAtLeast17 == null) { + isAtLeast17 = JavaVersionService.getInstance().isAtLeast(place, JavaSdkVersion.JDK_1_7); + } + if (!isTypeParameter || (isAtLeast17 != null && isAtLeast17)) { + PsiClass aClass = (PsiClass)placeParent; + + if (memberClass != null && aClass.isInheritor(memberClass, true)) return aClass; + + lastClass = aClass; + } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java index 79d526ac8ac7..b3dbf527fb1e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java @@ -79,7 +79,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{ protected boolean isShadowed(final PsiMethod candidate) { if (myCurrentFileContext instanceof PsiImportStaticStatement) { - for (JavaResolveResult result : getResult()) { + for (JavaResolveResult result : getResults()) { if (result.getElement() != candidate && result.isAccessible() && !(result.getCurrentFileResolveScope() instanceof PsiImportStaticStatement)) return true; diff --git a/java/java-tests/java-tests.iml b/java/java-tests/java-tests.iml index 1750b2ea3852..38e0eb6d4c3d 100644 --- a/java/java-tests/java-tests.iml +++ b/java/java-tests/java-tests.iml @@ -17,7 +17,7 @@ - + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java new file mode 100644 index 000000000000..f105923eb1b1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.util.Iterator; + +public class Test { + public static void bar() { + Class> c = foo(); + } + + public static Class foo() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java index f203f95c25de..8bbd7b65154a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java @@ -7,7 +7,7 @@ interface Matcher { } interface ArgumentConstraintPhrases { - T with(Matcher matcher); + T with(Matcher matcher); boolean with(Matcher matcher); byte with(Matcher matcher); short with(Matcher matcher); @@ -19,7 +19,7 @@ interface ArgumentConstraintPhrases { class ExpectationGroupBuilder implements ArgumentConstraintPhrases { - public T with(final Matcher matcher) { + public T with(final Matcher matcher) { return null; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java new file mode 100644 index 000000000000..b046069c784a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java @@ -0,0 +1,48 @@ +/** @noinspection UnusedDeclaration*/ +interface Matcher { + + boolean matches(Object object); + + void _dont_implement_Matcher___instead_extend_BaseMatcher_(); +} + +interface ArgumentConstraintPhrases { + T with(Matcher matcher); + boolean with(Matcher matcher); + byte with(Matcher matcher); + int with(Matcher matcher); + long with(Matcher matcher); + float with(Matcher matcher); + double with(Matcher matcher); +} + +class ExpectationGroupBuilder implements ArgumentConstraintPhrases { + + public T with(final Matcher matcher) { + return null; + } + + public boolean with(final Matcher matcher) { + return false; + } + + public byte with(final Matcher matcher) { + return 0; + } + + public int with(final Matcher matcher) { + return 0; + } + + public long with(final Matcher matcher) { + return 0; + } + + public float with(final Matcher matcher) { + return 0; + } + + public double with(final Matcher matcher) { + return 0; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java new file mode 100644 index 000000000000..82ab1a7f8cdf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java @@ -0,0 +1,9 @@ +class A { + private int value = 1; + + static class B { + void print(T t) { + System.out.println(t.value); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java new file mode 100644 index 000000000000..ce2e57ded675 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java @@ -0,0 +1,9 @@ +class A { + private int value = 1; + + static class B { + void print(T t) { + System.out.println(t.value); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java index 5145e806c4b4..1a586323851c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java @@ -172,4 +172,48 @@ class My { public void test() { if (getSuperclass() == List.class); } +} + +class IDEA75178 { + void test(Set labels) { + final Matcher empty = isEmpty(); + assertThat(labels, empty); + assertAlsoThat(empty, labels); + } + + public static void assertThat(T actual, Matcher matcher) { throw new AssertionError(actual.toString() + matcher.toString());} + public static void assertAlsoThat(Matcher matcher, T actual) { throw new AssertionError(actual.toString() + matcher.toString());} + + public static Matcher isEmpty() { + return null; + } + + static class Matcher<T>{} + + class Foo {} + void testComment() { + Set foos = Collections.emptySet(); + assertThatComment(foos, hasSize(0)); + } + + Matcher> hasSize(int size) {return size == 0 ? null : null;} + void assertThatComment(T actual, Matcher matcher){ throw new AssertionError(actual.toString() + matcher.toString());} +} + +class IDEA66750 { + public void test() { + List> data = new ArrayList>(); + List> y = (List>)data; + System.out.println(y); + + ArrayList al = (ArrayList) new ArrayList(1); + System.out.println(al); + } +} + +class IDEA73377 { + public Iterator, ?>> iterator(Map map) { + //noinspection unchecked + return (Iterator, ?>>)map.entrySet().iterator(); + } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java new file mode 100644 index 000000000000..b9ea90a0502e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java @@ -0,0 +1,6 @@ +// "Iterate" "false" +class Test { + void foo() { + final Annotation[] annotations = getClass().getAnnotations(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java new file mode 100644 index 000000000000..6934fb76215a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java @@ -0,0 +1,14 @@ +// "Pull method 'foo' to 'Foo' and make it abstract" "true" +public class Test { + void bar() { + abstract class Foo { + abstract void foo(); + } + class FooImpl extends Foo { + @Override + void foo(){} + } + } +} + + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java new file mode 100644 index 000000000000..6cefa7bc162a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java @@ -0,0 +1,12 @@ +// "Pull method 'foo' to 'Foo' and make it abstract" "true" +public class Test { + void bar() { + class Foo {} + class FooImpl extends Foo { + @Override + void foo(){} + } + } +} + + diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml index 8a6459d2c612..83d038f968a4 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java new file mode 100644 index 000000000000..ae7482c76f32 --- /dev/null +++ b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java @@ -0,0 +1,3 @@ +public class ModuleSourceAsLibrarySource { + ModuleSourceAsLibrarySourceDep field; +} diff --git a/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java new file mode 100644 index 000000000000..78a8b08ecc6f --- /dev/null +++ b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java @@ -0,0 +1 @@ +public class ModuleSourceAsLibrarySourceDep {} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java index 02d1c996716b..a02a70ba3af8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java @@ -37,7 +37,7 @@ public class SuppressExternalTest extends UsefulTestCase { public void setUp() throws Exception { super.setUp(); final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory(); - final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder(); + final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture()); myFixture.setTestDataPath(PathManagerEx.getTestDataPath() + "/codeInsight/externalAnnotations"); final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index d33381ec1e2e..cb955b02e898 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -4,6 +4,8 @@ import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiClass; @@ -30,10 +32,24 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { @Override protected void setUp() throws Exception { super.setUp(); - LanguageLevel level = getTestName(false).contains("Level6") ? LanguageLevel.JDK_1_6 : LanguageLevel.JDK_1_5; + LanguageLevel level; + final String testName = getTestName(false); + if (testName.contains("Level17")) { + level = LanguageLevel.JDK_1_7; + } else if (testName.contains("Level6")) { + level = LanguageLevel.JDK_1_6; + } + else { + level = LanguageLevel.JDK_1_5; + } LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(level); } + @Override + protected Sdk getProjectJDK() { + return getTestName(false).contains("Jdk14") ? JavaSdkImpl.getMockJdk14() : super.getProjectJDK(); + } + public void testReferenceTypeParams() throws Exception { doTest(false); } public void testOverridingMethods() throws Exception { doTest(false); } public void testTypeParameterBoundsList() throws Exception { doTest(false); } @@ -85,6 +101,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testGenericExtendException() throws Exception { doTest(false); } public void testSameErasureDifferentReturnTypes() throws Exception { doTest(false); } + public void testSameErasureDifferentReturnTypesJdk14() throws Exception { doTest(false); } public void testDeepConflictingReturnTypes() throws Exception { doTest(false); } public void testInheritFromTypeParameter() throws Exception { doTest(false); } public void testAnnotationsAsPartOfModifierList() throws Exception { doTest(false); } @@ -98,6 +115,9 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testInnerClassRef() throws Exception { doTest(false); } public void testPrivateInnerClassRef() throws Exception { doTest(false); } public void testWideningCastToTypeParam() throws Exception { doTest(false); } + public void testCapturedWildcardAssignments() throws Exception { doTest(false);} + public void testTypeParameterBoundVisibility() throws Exception { doTest(false);} + public void testTypeParameterBoundVisibilityJdk14() throws Exception { doTest(false);} public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java index 2d6115085c70..5754db7eb2cb 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java @@ -34,6 +34,10 @@ public class PullOverrideMethodUpFixTest extends LightQuickFixTestCase { doSingleTest("4.java"); } + public void test6() throws Exception { + doSingleTest("6.java"); + } + public void testRefactoringIntentionsAvailable() throws Exception { doTestActionAvailable(5, "Pull members up"); doTestActionAvailable(5, "Extract interface"); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy index 23e2dcadaf3f..2b537de76906 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -618,7 +618,7 @@ class Test { doTest(before, toPaste2, expected) } - def testPlainTextPaste() { + void testPlainTextPaste() { def before = '''\ line1 line2 @@ -628,7 +628,7 @@ class Test { def toPaste = '''\ line to paste #1 - line to paste #2 + line to paste #2\ ''' @@ -641,10 +641,33 @@ line to paste #1 doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) } - def testPlainTextPasteWithCompleteReplacement() { + void "test plain text when pasted string ends by line feed"() { + def before = '''\ + line1 + line2 + +''' + + def toPaste = + '''\ +line to paste #1 +line to paste #2 +''' + + def expected = '''\ + line1 + line2 + line to paste #1 + line to paste #2 + +''' + doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) + } + + void "test plain text when caret is after selection"() { def before = '''\ line1 - line2\ +\ ''' def toPaste = @@ -655,32 +678,14 @@ line to paste #2 def expected = '''\ + line1 line to paste #1 line to paste #2 ''' doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) } - def testPlainTextMultilinePasteWithCaretAfterSelection() { - def before = '''\ - line1\ -''' - - def toPaste = - '''\ -line to paste #1 -line to paste #2 -''' - - - def expected = '''\ -line to paste #1 -line to paste #2 -''' - doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) - } - - def testPlainTextThatStartsByLineFeed() { + void testPlainTextThatStartsByLineFeed() { def before = '''\ line 1 # item1 @@ -715,6 +720,37 @@ line 1 doTest(before, toPaste2, expected2, StdFileTypes.PLAIN_TEXT) } + void "test formatter-based paste that starts with white space"() { + def before = '''\ +class Test { + int i; + int j; + + void test() { + + } +} +''' + + def toPaste = '''\ + int i; + int j;\ +''' + + def expected = '''\ +class Test { + int i; + int j; + + void test() { + int i; + int j; + } +} +''' + doTest(before, toPaste, expected) + } + def doTest(String before, toPaste, expected, FileType fileType = StdFileTypes.JAVA) { myFixture.configureByText(fileType, before) @@ -732,6 +768,7 @@ line 1 finally { settings.REFORMAT_ON_PASTE = old } + myFixture.editor.selectionModel.removeSelection() myFixture.checkResult(expected) } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy index 3b48d5e41fd3..5d13114d3e7f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy @@ -167,6 +167,32 @@ class Test { assertEquals(2, closureFolds.size()) } + public void "test closure folding doesn't expand when editing inside"() { + def text = """\ +class Test { + void test() { + new Runnable() { + public void run() { + System.out.println(); + } + }; + } +} +""" + + configure text + def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl + def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assertNotNull closureStartFold + assertFalse closureStartFold.expanded + assert text.substring(closureStartFold.endOffset).startsWith('System') //one line closure + + myFixture.type('2') + myFixture.doHighlighting() + closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assert closureStartFold + } + public void testFindInFolding() { def text = """\ class Test { diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java index c2655b28e60e..bb012a5b2665 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java @@ -15,8 +15,9 @@ */ package com.intellij.codeInspection; -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.ex.InspectionToolRegistrar; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.codeInspection.ex.*; import com.intellij.openapi.util.JDOMUtil; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.testFramework.LightIdeaTestCase; @@ -25,6 +26,9 @@ import org.jdom.Element; import org.jdom.JDOMException; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import static com.intellij.testFramework.PlatformTestUtil.assertElementsEqual; @@ -171,4 +175,63 @@ public class InspectionProfileTest extends LightIdeaTestCase { profile.writeExternal(copy); assertElementsEqual(element, copy); } + + public void testLockProfile() throws Exception { + + final List list = new ArrayList(); + list.add(createTool("foo")); + + InspectionToolRegistrar registrar = new InspectionToolRegistrar(null) { + @Override + public List createTools() { + LocalInspectionEP foo = new LocalInspectionEP(); + foo.shortName = "foo"; + return list; + } + }; + + InspectionProfileImpl profile = new InspectionProfileImpl("Foo", registrar, InspectionProfileManager.getInstance()); + profile.setBaseProfile(null); + List tools = profile.getAllTools(); + assertEquals(1, tools.size()); + ModifiableModel model = profile.getModifiableModel(); + model.lockProfile(true); + model.commit(); + Element element = new Element("element"); + profile.writeExternal(element); + + list.add(createTool("bar")); + + profile = new InspectionProfileImpl("Foo", registrar, InspectionProfileManager.getInstance()); + profile.readExternal(element); + + profile.setBaseProfile(null); + tools = profile.getAllTools(); + assertEquals(2, tools.size()); + + assertTrue(profile.isProfileLocked()); + assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("bar"))); + } + + public void testGlobalInspectionContext() throws Exception { + InspectionProfileImpl profile = new InspectionProfileImpl("Foo"); + profile.disableAllTools(); + profile.enableTool(new UnusedDeclarationInspection().getShortName()); + + GlobalInspectionContextImpl context = ((InspectionManagerEx)InspectionManager.getInstance(getProject())).createNewGlobalContext(false); + context.setExternalProfile(profile); + context.initializeTools(new ArrayList(), new ArrayList(), new ArrayList()); + Map tools = context.getTools(); + assertEquals(1, tools.size()); + } + + private static LocalInspectionToolWrapper createTool(String s) { + LocalInspectionEP foo = new LocalInspectionEP(); + foo.shortName = s; + foo.displayName = s; + foo.groupDisplayName = s; + foo.level = "ERROR"; + foo.enabledByDefault = true; + return new LocalInspectionToolWrapper(foo); + } } diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java index b67073bfcbca..8eab910851f0 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java @@ -8,6 +8,7 @@ import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -155,6 +156,16 @@ public class ResolveClassTest extends ResolveTestCase { assertNull(target); } + public void testModuleSourceAsLibrarySource() throws Exception { + final PsiReference ref = configure(); + final VirtualFile file = ref.getElement().getContainingFile().getVirtualFile(); + assertNotNull(file); + createFile(myModule, file.getParent(), "ModuleSourceAsLibrarySourceDep.java", loadFile("class/ModuleSourceAsLibrarySourceDep.java")); + addLibraryToRoots(file.getParent(), OrderRootType.SOURCES); + + assertInstanceOf(ref.resolve(), PsiClass.class); + } + public void testStaticImportInTheSameClass() throws Exception { PsiReference ref = configure(); long start = System.currentTimeMillis(); diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy new file mode 100644 index 000000000000..ceb2bbd93df6 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.resolve + +import com.intellij.openapi.application.ex.PathManagerEx +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.testFramework.PsiTestUtil +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase + +/** + * @author peter + */ +class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase { + + public void "test prefer current library when navigation from its source"() { + def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib") + def nanoJar = lib.children.find { it.name.startsWith("nanoxml") } + def nanoSrc = lib.findChild("src").children.find { it.name.startsWith("nanoxml") } + + def jarCopy = myFixture.copyFileToProject(nanoJar.path, 'lib/nanoJar.jar') + def srcCopy = myFixture.copyFileToProject(nanoSrc.path, 'lib/nanoSrc.zip') + + PsiTestUtil.addLibrary(myModule, 'nano1', lib.path, ["/$nanoJar.name!/"] as String[], ["/src/$nanoSrc.name!/"] as String[]) + PsiTestUtil.addLibrary(myModule, 'nano2', jarCopy.parent.path, ["/$jarCopy.name!/"] as String[], ["/$srcCopy.name!/"] as String[]) + + def parsers = JavaPsiFacade.getInstance(project).findClasses('net.n3.nanoxml.IXMLParser', GlobalSearchScope.allScope(project)) + assert parsers.size() == 2 + + def file0 = parsers[0].navigationElement.containingFile + assert file0.virtualFile.path.startsWith(nanoSrc.path) + assert file0.findReferenceAt(file0.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(nanoSrc.path) + + def file1 = parsers[1].navigationElement.containingFile + assert file1.virtualFile.path.startsWith(srcCopy.path) + assert file1.findReferenceAt(file1.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(srcCopy.path) + + } + +} diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java new file mode 100644 index 000000000000..859e269fbd1b --- /dev/null +++ b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.projectRoots; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.psi.PsiElement; + +/** + * User: anna + * Date: 3/28/12 + */ +public class JavaSdkVersionUtil { + public static boolean isAtLeast(PsiElement element, JavaSdkVersion minVersion) { + final Module module = ModuleUtil.findModuleForPsiElement(element); + if (module != null) { + final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { + final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk); + return version != null && version.isAtLeast(minVersion); + } + } + return false; + } +} diff --git a/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java b/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java index 35d132f23637..ec471600d9f5 100644 --- a/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java @@ -216,7 +216,7 @@ public abstract class PsiTestCase extends ModuleTestCase { addLibraryToRoots(myModule, jarFile, rootType); } - protected static void addLibraryToRoots(final Module module, final VirtualFile jarFile, final OrderRootType rootType) { + protected static void addLibraryToRoots(final Module module, final VirtualFile root, final OrderRootType rootType) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -224,7 +224,7 @@ public abstract class PsiTestCase extends ModuleTestCase { final ModifiableRootModel rootModel = manager.getModifiableModel(); final Library jarLibrary = rootModel.getModuleLibraryTable().createLibrary(); final Library.ModifiableModel libraryModel = jarLibrary.getModifiableModel(); - libraryModel.addRoot(jarFile, rootType); + libraryModel.addRoot(root, rootType); libraryModel.commit(); rootModel.commit(); } diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml index 9c5878d1e2f3..e27c35289a56 100644 --- a/jps/jps-builders/jps-builders.iml +++ b/jps/jps-builders/jps-builders.iml @@ -12,7 +12,7 @@ - + diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java index f2fdd71e4b0d..febbe3880eb7 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java +++ b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java @@ -9,4 +9,5 @@ public interface GlobalOptions { String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process"; String HOSTNAME_OPTION = "localhost.name"; String PING_INTERVAL_MS_OPTION = "server.ping.interval"; + String GENERATE_CLASSPATH_INDEX_OPTION = "generate.classpath.index"; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java b/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java new file mode 100644 index 000000000000..508abe015b3f --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java @@ -0,0 +1,18 @@ +package org.jetbrains.jps.api; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author Eugene Zhuravlev + * Date: 3/29/12 + */ +public class SharedThreadPool { + public static final ExecutorService INSTANCE = Executors.newCachedThreadPool(); + public static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() { + @Override + public void submit(Runnable runnable) { + INSTANCE.submit(runnable); + } + }; +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java index 8c762adf18b8..19544249f0c5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java +++ b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java @@ -34,7 +34,7 @@ public class SimpleProtobufClient { private final AtomicReference myState = new AtomicReference(State.DISCONNECTED); protected final ChannelPipelineFactory myPipelineFactory; protected final ChannelFactory myChannelFactory; - protected ChannelFuture myConnectFuture; + protected volatile ChannelFuture myConnectFuture; private final ProtobufClientMessageHandler myMessageHandler; public SimpleProtobufClient(final MessageLite msgDefaultInstance, final AsyncTaskExecutor asyncExec, final UUIDGetter uuidGetter) { @@ -146,8 +146,9 @@ public class SimpleProtobufClient { public final RequestFuture sendMessage(final UUID messageId, MessageLite message, @Nullable final T responseHandler, @Nullable final RequestFuture.CancelAction cancelAction) { final RequestFuture requestFuture = new RequestFuture(responseHandler, messageId, cancelAction); myMessageHandler.registerFuture(messageId, requestFuture); - final Channel channel = myConnectFuture.getChannel(); - if (channel.isConnected()) { + final ChannelFuture connectFuture = myConnectFuture; + final Channel channel = connectFuture != null? connectFuture.getChannel() : null; + if (channel != null && channel.isConnected()) { Channels.write(channel, message).addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index 62b2c1fd2cb4..dbe6eecef318 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -30,7 +30,7 @@ public class BuilderRegistry { myTasksExecutor = Executors.newFixedThreadPool(runtime.availableProcessors()); runtime.addShutdownHook(new Thread() { public void run() { - myTasksExecutor.shutdownNow(); + myTasksExecutor.shutdown(); } }); @@ -70,7 +70,7 @@ public class BuilderRegistry { } public void shutdown() { - myTasksExecutor.shutdownNow(); + myTasksExecutor.shutdown(); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index f59e2c6a0da9..5d493a8dca64 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -9,7 +9,9 @@ import com.intellij.util.io.MappingFailedException; import com.intellij.util.io.PersistentEnumerator; import org.jetbrains.jps.*; import org.jetbrains.jps.api.CanceledStatus; +import org.jetbrains.jps.api.GlobalOptions; import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor; import org.jetbrains.jps.incremental.java.JavaBuilder; import org.jetbrains.jps.incremental.java.JavaBuilderLogger; @@ -21,10 +23,13 @@ import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.incremental.storage.SourceToOutputMapping; import org.jetbrains.jps.server.ProjectDescriptor; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** @@ -35,6 +40,8 @@ public class IncProjectBuilder { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.IncProjectBuilder"); public static final String COMPILE_SERVER_NAME = "COMPILE SERVER"; + private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index"; + private static final boolean GENERATE_CLASSPATH_INDEX = "true".equals(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION)); private final ProjectDescriptor myProjectDescriptor; private final BuilderRegistry myBuilderRegistry; @@ -54,6 +61,7 @@ public class IncProjectBuilder { private float myModulesProcessed = 0.0f; private final float myTotalModulesWork; private final int myTotalModuleLevelBuilderCount; + private final List myAsyncTasks = new ArrayList(); public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map builderParams, CanceledStatus cs) { myProjectDescriptor = pd; @@ -131,6 +139,15 @@ public class IncProjectBuilder { finally { memWatcher.stop(); flushContext(context); + // wait for the async tasks + for (Future task : myAsyncTasks) { + try { + task.get(); + } + catch (Throwable th) { + LOG.info(th); + } + } } } @@ -309,16 +326,18 @@ public class IncProjectBuilder { } } - private void buildChunk(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + private void buildChunk(CompileContext context, final ModuleChunk chunk) throws ProjectBuildException { + boolean doneSomething = false; try { context.ensureFSStateInitialized(chunk); if (context.isMake()) { processDeletedPaths(context, chunk); + doneSomething |= context.hasRemovedSources(); } context.onChunkBuildStart(chunk); - runModuleLevelBuilders(context, chunk); + doneSomething = runModuleLevelBuilders(context, chunk); } catch (ProjectBuildException e) { throw e; @@ -343,11 +362,59 @@ public class IncProjectBuilder { } finally { Paths.CHUNK_REMOVED_SOURCES_KEY.set(context, null); + if (doneSomething && GENERATE_CLASSPATH_INDEX) { + final boolean forTests = context.isCompilingTests(); + final Future future = SharedThreadPool.INSTANCE.submit(new Runnable() { + @Override + public void run() { + createClasspathIndex(chunk, forTests); + } + }); + myAsyncTasks.add(future); + } } } } } + private static void createClasspathIndex(final ModuleChunk chunk, boolean forTests) { + final Set outputPaths = new LinkedHashSet(); + for (Module module : chunk.getModules()) { + if (forTests) { + outputPaths.add(new File(module.getTestOutputPath())); + } + else { + outputPaths.add(new File(module.getOutputPath())); + } + } + for (File outputRoot : outputPaths) { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outputRoot, CLASSPATH_INDEX_FINE_NAME))); + try { + writeIndex(writer, outputRoot, ""); + } + finally { + writer.close(); + } + } + catch (IOException e) { + // Ignore. Failed to create optional classpath index + } + } + } + + private static void writeIndex(final BufferedWriter writer, final File file, final String path) throws IOException { + writer.write(path); + writer.write('\n'); + final File[] files = file.listFiles(); + if (files != null) { + for (File child : files) { + writeIndex(writer, child, path + "/" + child.getName()); + } + } + } + + private void processDeletedPaths(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { try { // cleanup outputs @@ -420,13 +487,14 @@ public class IncProjectBuilder { } } - private void runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + // return true if changed something, false otherwise + private boolean runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + boolean doneSomething = false; boolean rebuildFromScratchRequested = false; float stageCount = myTotalModuleLevelBuilderCount; final int modulesInChunk = chunk.getModules().size(); int buildersPassed = 0; boolean nextPassRequired; - do { nextPassRequired = false; context.beforeCompileRound(chunk); @@ -448,6 +516,8 @@ public class IncProjectBuilder { } final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk); + doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE); + if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) { throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop"); } @@ -492,6 +562,8 @@ public class IncProjectBuilder { } } while (nextPassRequired); + + return doneSomething; } private void runProjectLevelBuilders(CompileContext context) throws ProjectBuildException { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java index d503e83bff8e..5f442ca56ae0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java @@ -32,7 +32,7 @@ public abstract class ModuleLevelBuilder extends Builder { } public static enum ExitCode { - OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED + NOTHING_DONE, OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED } public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException; 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 10b03b898693..0e5360167d20 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 @@ -1,5 +1,7 @@ package org.jetbrains.jps.incremental.java; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.execution.process.BaseOSProcessHandler; import com.intellij.openapi.application.PathManager; @@ -31,13 +33,11 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.EmptyVisitor; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; import java.net.URL; -import java.net.URLClassLoader; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @@ -238,7 +238,7 @@ public class JavaBuilder extends ModuleLevelBuilder { private ExitCode compile(final CompileContext context, ModuleChunk chunk, Collection files, Collection forms) throws Exception { - ExitCode exitCode = ExitCode.OK; + ExitCode exitCode = ExitCode.NOTHING_DONE; final boolean hasSourcesToCompile = !files.isEmpty() || !forms.isEmpty(); @@ -263,6 +263,7 @@ public class JavaBuilder extends ModuleLevelBuilder { DELTA_MAPPINGS_CALLBACK_KEY.set(context, delta.getCallback()); try { if (hasSourcesToCompile) { + exitCode = ExitCode.OK; final Set sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.emptySet()); final String chunkName = getChunkPresentableName(chunk); @@ -274,15 +275,14 @@ public class JavaBuilder extends ModuleLevelBuilder { context.checkCanceled(); if (!forms.isEmpty() || addNotNullAssertions) { - final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, outputSink); + final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, context.isCompilingTests()); + final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, chunkSourcePath, outputSink); try { if (!forms.isEmpty()) { try { context.processMessage(new ProgressMessage("Instrumenting forms [" + chunkName + "]")); - final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, context.isCompilingTests()); - final ClassLoader loader = createInstrumentationClassLoader(platformCp, classpath, chunkSourcePath, outputSink); - instrumentForms(context, chunk, chunkSourcePath, loader, finder, forms, outputSink); + instrumentForms(context, chunk, chunkSourcePath, finder, forms, outputSink); } finally { context.processMessage(new ProgressMessage("Finished instrumenting forms [" + chunkName + "]")); @@ -529,22 +529,24 @@ public class JavaBuilder extends ModuleLevelBuilder { private static InstrumentationClassFinder createInstrumentationClassFinder(Collection platformCp, Collection classpath, - final OutputFilesSink outputSink) throws MalformedURLException { + Map chunkSourcePath, final OutputFilesSink outputSink) throws MalformedURLException { final URL[] platformUrls = new URL[platformCp.size()]; int index = 0; for (File file : platformCp) { platformUrls[index++] = file.toURI().toURL(); } - final URL[] urls = new URL[classpath.size() + 1]; - index = 0; + final List urls = new ArrayList(classpath.size() + chunkSourcePath.size() + 1); for (File file : classpath) { - urls[index++] = file.toURI().toURL(); + urls.add(file.toURI().toURL()); } - urls[index++] = getResourcePath(GridConstraints.class).toURI().toURL(); // forms_rt.jar + urls.add(getResourcePath(GridConstraints.class).toURI().toURL()); // forms_rt.jar //urls.add(getResourcePath(CellConstraints.class).toURI().toURL()); // jgoodies-forms - - return new InstrumentationClassFinder(platformUrls, urls) { + for (File file : chunkSourcePath.keySet()) { // sourcepath for loading forms resources + urls.add(file.toURI().toURL()); + } + + return new InstrumentationClassFinder(platformUrls, urls.toArray(new URL[urls.size()])) { protected InputStream lookupClassBeforeClasspath(String internalClassName) { final OutputFileObject.Content content = outputSink.lookupClassBytes(internalClassName.replace("/", ".")); if (content != null) { @@ -555,23 +557,6 @@ public class JavaBuilder extends ModuleLevelBuilder { }; } - private static ClassLoader createInstrumentationClassLoader(Collection platformCp, Collection classpath, - Map chunkSourcePath, - OutputFilesSink outputSink) throws MalformedURLException { - final List urls = new ArrayList(); - for (Collection cp : Arrays.asList(platformCp, classpath)) { - for (File file : cp) { - urls.add(file.toURI().toURL()); - } - } - urls.add(getResourcePath(GridConstraints.class).toURI().toURL()); // forms_rt.jar - //urls.add(getResourcePath(CellConstraints.class).toURI().toURL()); // jgoodies-forms - for (File file : chunkSourcePath.keySet()) { - urls.add(file.toURI().toURL()); - } - return new CompiledClassesLoader(outputSink, urls.toArray(new URL[urls.size()])); - } - private static final Key> JAVAC_OPTIONS = Key.create("_javac_options_"); private static final Key> JAVAC_VM_OPTIONS = Key.create("_javac_vm_options_"); @@ -713,7 +698,6 @@ public class JavaBuilder extends ModuleLevelBuilder { private static void instrumentForms(CompileContext context, ModuleChunk chunk, final Map chunkSourcePath, - final ClassLoader loader, final InstrumentationClassFinder finder, Collection formsToInstrument, OutputFilesSink outputSink) throws ProjectBuildException { @@ -731,7 +715,7 @@ public class JavaBuilder extends ModuleLevelBuilder { for (File formFile : formsToInstrument) { final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(formFile.toURI().toURL(), new CompiledClassPropertiesProvider(loader)); + rootContainer = Utils.getRootContainer(formFile.toURI().toURL(), new CompiledClassPropertiesProvider(finder.getLoader())); } catch (AlienFormFileException e) { // ignore non-IDEA forms @@ -774,7 +758,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final int version = getClassFileVersion(classReader); final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader, nestedFormsLoader, false, classWriter); + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, nestedFormsLoader, false, classWriter); final byte[] patchedBytes = codeGenerator.patchClass(classReader); if (patchedBytes != null) { outputClassFile.updateContent(patchedBytes); @@ -884,7 +868,8 @@ public class JavaBuilder extends ModuleLevelBuilder { myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "OutOfMemoryError: insufficient memory")); } else { - myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, line)); + final BuildMessage.Kind kind = line.toLowerCase(Locale.US).contains("error")? BuildMessage.Kind.ERROR : BuildMessage.Kind.INFO; + myContext.processMessage(new CompilerMessage(BUILDER_NAME, kind, line)); } } } @@ -923,42 +908,6 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - public static class InstrumenterClassWriter extends ClassWriter { - private final InstrumentationClassFinder myFinder; - - public InstrumenterClassWriter(int flags, final InstrumentationClassFinder finder) { - super(flags); - myFinder = finder; - } - - protected String getCommonSuperClass(final String type1, final String type2) { - try { - final InstrumentationClassFinder.PseudoClass cls1 = myFinder.loadClass(type1); - final InstrumentationClassFinder.PseudoClass cls2 = myFinder.loadClass(type2); - if (cls1.isAssignableFrom(cls2)) { - return cls1.getName(); - } - if (cls2.isAssignableFrom(cls1)) { - return cls2.getName(); - } - if (cls1.isInterface() || cls2.isInterface()) { - return "java/lang/Object"; - } - else { - InstrumentationClassFinder.PseudoClass c = cls1; - do { - c = c.getSuperClass(); - } - while (!c.isAssignableFrom(cls2)); - return c.getName(); - } - } - catch (Exception e) { - throw new RuntimeException(e.toString(), e); - } - } - } - private static class MyNestedFormLoader implements NestedFormLoader { private final Map mySourceRoots; private final Collection myOutputRoots; @@ -1039,27 +988,6 @@ public class JavaBuilder extends ModuleLevelBuilder { return new File(PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class")); } - private static class CompiledClassesLoader extends URLClassLoader { - private final OutputFilesSink mySink; - - public CompiledClassesLoader(OutputFilesSink sink, URL[] urls) { - super(urls, null); - mySink = sink; - } - - protected Class findClass(String name) throws ClassNotFoundException { - final OutputFileObject.Content content = mySink.lookupClassBytes(name); - if (content != null) { - return defineClass(name, content.getBuffer(), content.getOffset(), content.getLength()); - } - return super.findClass(name); - } - - public URL findResource(String name) { - return super.findResource(name); - } - } - private class ClassProcessingConsumer implements OutputFileConsumer { private final CompileContext myCompileContext; private final OutputFileConsumer myDelegateOutputFileSink; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java index 06e142335840..21238fa03190 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java @@ -1,6 +1,7 @@ package org.jetbrains.jps.incremental.resources; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.jps.Module; import org.jetbrains.jps.ModuleChunk; @@ -38,12 +39,14 @@ public class ResourcesBuilder extends ModuleLevelBuilder { } try { final ResourcePatterns finalPatterns = patterns; + final Ref doneSomething = new Ref(false); context.processFilesToRecompile(chunk, new FileProcessor() { public boolean apply(final Module module, final File file, final String sourceRoot) throws IOException { if (finalPatterns.isResourceFile(file, sourceRoot)) { try { context.processMessage(new ProgressMessage("Copying " + file.getPath())); final String moduleName = module.getName().toLowerCase(Locale.US); + doneSomething.set(true); copyResource(context, module, file, sourceRoot, context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests())); } catch (IOException e) { @@ -56,7 +59,7 @@ public class ResourcesBuilder extends ModuleLevelBuilder { } }); - return ExitCode.OK; + return doneSomething.get()? ExitCode.OK : ExitCode.NOTHING_DONE; } catch (Exception e) { throw new ProjectBuildException(e.getMessage(), e); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java index 75a3e7cb6e1d..136f07ce4798 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java @@ -2,31 +2,22 @@ package org.jetbrains.jps.javac; import org.jboss.netty.channel.MessageEvent; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.api.AsyncTaskExecutor; import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.client.SimpleProtobufClient; import org.jetbrains.jps.client.UUIDGetter; import java.io.File; import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * @author Eugene Zhuravlev * Date: 1/22/12 */ public class JavacServerClient extends SimpleProtobufClient{ - private static final ExecutorService ourExecutors = Executors.newCachedThreadPool(); - private static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() { - @Override - public void submit(Runnable runnable) { - ourExecutors.submit(runnable); - } - }; public JavacServerClient() { - super(JavacRemoteProto.Message.getDefaultInstance(), ASYNC_EXEC, new UUIDGetter() { + super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.ASYNC_EXEC, new UUIDGetter() { @NotNull public UUID getSessionUUID(@NotNull MessageEvent e) { final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage(); diff --git a/jps/jps.iml b/jps/jps.iml index 44d24bb8c46f..c08dac3c1a16 100644 --- a/jps/jps.iml +++ b/jps/jps.iml @@ -34,6 +34,7 @@ + diff --git a/jps/src/org/jetbrains/jps/ModuleBuildState.groovy b/jps/src/org/jetbrains/jps/ModuleBuildState.groovy index b82ef2422486..52f15608c417 100644 --- a/jps/src/org/jetbrains/jps/ModuleBuildState.groovy +++ b/jps/src/org/jetbrains/jps/ModuleBuildState.groovy @@ -1,7 +1,7 @@ package org.jetbrains.jps import com.intellij.ant.InstrumentationUtil.FormInstrumenter -import com.intellij.ant.PseudoClassLoader +import com.intellij.compiler.instrumentation.InstrumentationClassFinder import org.jetbrains.ether.ProjectWrapper import org.jetbrains.ether.dependencyView.Callbacks.Backend @@ -13,7 +13,7 @@ class ModuleBuildState { boolean tests Backend callback FormInstrumenter formInstrumenter - PseudoClassLoader loader + InstrumentationClassFinder loader ProjectWrapper projectWrapper List sourceFiles List sourceRoots diff --git a/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy b/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy index babacca78d33..1c7537687a48 100644 --- a/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy +++ b/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy @@ -3,6 +3,7 @@ package org.jetbrains.jps.builders import com.intellij.ant.InstrumentationUtil import com.intellij.ant.InstrumentationUtil.FormInstrumenter import com.intellij.ant.PrefixedPath +import com.intellij.compiler.instrumentation.InstrumentationClassFinder import org.apache.tools.ant.BuildListener import org.jetbrains.ether.ProjectWrapper import org.jetbrains.ether.dependencyView.AntListener @@ -332,17 +333,13 @@ class JetBrainsInstrumentations implements ModuleBuilder { def processModule(ModuleBuildState state, ModuleChunk moduleChunk, ProjectBuilder projectBuilder) { if (state.loader == null) { - final StringBuilder cp = new StringBuilder() - - cp.append(state.targetFolder) - cp.append(File.pathSeparator) - + final ArrayList urls = new ArrayList(); + urls.add(new File(state.targetFolder).toURL()); state.classpath.each { - cp.append(it) - cp.append(File.pathSeparator) + urls.add(new File(it).toURL()); } - state.loader = InstrumentationUtil.createPseudoClassLoader(cp.toString()) + state.loader = new InstrumentationClassFinder((URL[])urls.toArray(new URL[urls.size()])) final List formFiles = new ArrayList(); final ProjectWrapper pw = state.projectWrapper; @@ -409,6 +406,9 @@ class JetBrainsInstrumentations implements ModuleBuilder { InstrumentationUtil.instrumentNotNull(new File(state.targetFolder + File.separator + it + ".class"), state.loader) } } + if (state.loader != null) { + state.loader.releaseResources(); + } } } diff --git a/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy b/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy index 7ca3bb2dc8f3..a235e2fd9c97 100644 --- a/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy +++ b/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy @@ -1,17 +1,17 @@ package org.jetbrains.jps.builders.javacApi -import com.intellij.ant.InstrumentationUtil -import javax.tools.JavaCompiler -import javax.tools.JavaCompiler.CompilationTask -import javax.tools.JavaFileObject -import javax.tools.StandardLocation -import javax.tools.ToolProvider import org.jetbrains.jps.ModuleBuildState import org.jetbrains.jps.ModuleChunk import org.jetbrains.jps.ProjectBuilder import org.jetbrains.jps.Sdk import org.jetbrains.jps.builders.JavaFileCollector +import javax.tools.JavaCompiler +import javax.tools.JavaCompiler.CompilationTask +import javax.tools.JavaFileObject +import javax.tools.StandardLocation +import javax.tools.ToolProvider + /** * @author nik */ @@ -89,7 +89,7 @@ class Java16ApiCompiler { cp.append(state.targetFolder) fileManager.setLocation(StandardLocation.CLASS_PATH, classpath) - fileManager.setProperties(state.callback, InstrumentationUtil.createPseudoClassLoader(cp.toString())) + fileManager.setProperties(state.callback, toURLs(cp.toString())) Iterable toCompile = fileManager.getJavaFileObjectsFromFiles(filesToCompile) StringWriter out = new StringWriter() @@ -109,4 +109,13 @@ class Java16ApiCompiler { } } + private URL[] toURLs(final String classPath) { + final List urls = new ArrayList(); + for (StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer.hasMoreTokens();) { + final String s = tokenizer.nextToken(); + urls.add(new File(s).toURL()); + } + return (URL[])urls.toArray(new URL[urls.size()]); + } + } diff --git a/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java b/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java index a4617a93289d..d7163000ea5d 100644 --- a/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java +++ b/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java @@ -1,7 +1,7 @@ package org.jetbrains.jps.builders.javacApi; import com.intellij.ant.InstrumentationUtil; -import com.intellij.ant.PseudoClassLoader; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.DefaultFileManager; import com.sun.tools.javac.util.List; @@ -14,10 +14,9 @@ import javax.lang.model.SourceVersion; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileObject; import javax.tools.JavaFileObject; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.lang.reflect.Field; +import java.net.URL; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -34,11 +33,17 @@ public class OptimizedFileManager extends DefaultFileManager { private final Map myArchives; private final Map myIsFile = new ConcurrentHashMap(); private Callbacks.Backend callback; - private PseudoClassLoader loader; + private InstrumentationClassFinder classFinder; + private Map myCompiledClasses = new HashMap(); - public void setProperties(final Callbacks.Backend c, final PseudoClassLoader l) { + public void setProperties(final Callbacks.Backend c, final URL[] classpath) { callback = c; - loader = l; + classFinder = new InstrumentationClassFinder(classpath) { + protected InputStream lookupClassBeforeClasspath(String internalClassName) { + final byte[] bytes = myCompiledClasses.get(internalClassName); + return bytes != null? new ByteArrayInputStream(bytes) : null; + } + }; } public OptimizedFileManager() { @@ -201,7 +206,7 @@ public class OptimizedFileManager extends DefaultFileManager { final byte[] buffer = Arrays.copyOfRange(b, off, len); if (kind.equals(JavaFileObject.Kind.CLASS)) { - loader.defineClass(className.replaceAll("\\.", "/"), buffer); + myCompiledClasses.put(className.replace('.', '/'), buffer); if (callback != null) { final ClassReader reader = new ClassReader(buffer); @@ -212,7 +217,7 @@ public class OptimizedFileManager extends DefaultFileManager { public void commit() throws IOException { final OutputStream result = superOpenOutputStream(); - final byte[] instrumented = InstrumentationUtil.instrumentNotNull(buffer, loader); + final byte[] instrumented = InstrumentationUtil.instrumentNotNull(buffer, classFinder); if (instrumented != null) { result.write(instrumented); @@ -247,5 +252,8 @@ public class OptimizedFileManager extends DefaultFileManager { } myWriters.clear(); + if (classFinder != null) { + classFinder.releaseResources(); + } } } diff --git a/platform/core-api/src/com/intellij/psi/PsiElement.java b/platform/core-api/src/com/intellij/psi/PsiElement.java index 99bc7789c90c..fa58ea3d3797 100644 --- a/platform/core-api/src/com/intellij/psi/PsiElement.java +++ b/platform/core-api/src/com/intellij/psi/PsiElement.java @@ -46,7 +46,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * Returns the project to which the PSI element belongs. * * @return the project instance. - * @throws PsiInvalidElementAccessException if this element is invalid + * @throws PsiInvalidElementAccessException + * if this element is invalid */ @NotNull Project getProject() throws PsiInvalidElementAccessException; @@ -56,7 +57,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the language instance. */ - @NotNull Language getLanguage(); + @NotNull + Language getLanguage(); /** * Returns the PSI manager for the project to which the PSI element belongs. @@ -71,7 +73,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the array of child elements. */ - @NotNull PsiElement[] getChildren(); + @NotNull + PsiElement[] getChildren(); /** * Returns the parent of the PSI element. @@ -85,34 +88,40 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the first child, or null if the element has no children. */ - @Nullable PsiElement getFirstChild(); + @Nullable + PsiElement getFirstChild(); /** * Returns the last child of the PSI element. * * @return the last child, or null if the element has no children. */ - @Nullable PsiElement getLastChild(); + @Nullable + PsiElement getLastChild(); /** * Returns the next sibling of the PSI element. * * @return the next sibling, or null if the node is the last in the list of siblings. */ - @Nullable PsiElement getNextSibling(); + @Nullable + PsiElement getNextSibling(); /** * Returns the previous sibling of the PSI element. * * @return the previous sibling, or null if the node is the first in the list of siblings. */ - @Nullable PsiElement getPrevSibling(); + @Nullable + PsiElement getPrevSibling(); /** * Returns the file containing the PSI element. - * @throws PsiInvalidElementAccessException if this element is invalid + * * @return the file instance, or null if the PSI element is not contained in a file (for example, - * the element represents a package or directory). + * the element represents a package or directory). + * @throws PsiInvalidElementAccessException + * if this element is invalid */ PsiFile getContainingFile() throws PsiInvalidElementAccessException; @@ -178,7 +187,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the element text as a character array. */ - @NotNull char[] textToCharArray(); + @NotNull + char[] textToCharArray(); /** * Returns the PSI element which should be used as a navigation target @@ -246,7 +256,7 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * Creates a copy of the file containing the PSI element and returns the corresponding * element in the created copy. Resolve operations performed on elements in the copy - * of the file will resolve to elements in the copy, not in the original file. + * of the file will resolve to elements in the copy, not in the original file. * * @return the element in the file copy corresponding to this element. */ @@ -304,9 +314,9 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * Adds a range of elements as children to this PSI element, before the specified anchor element. * - * @param first the first child element to add. - * @param last the last child element to add (must have the same parent as first) - * @param anchor the anchor before which the child element is inserted (must be a child of this PSI element) + * @param first the first child element to add. + * @param last the last child element to add (must have the same parent as first) + * @param anchor the anchor before which the child element is inserted (must be a child of this PSI element) * @return the first child element which was actually added (either first or its copy). * @throws IncorrectOperationException if the modification is not supported or not possible for some reason. */ @@ -315,9 +325,9 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * Adds a range of elements as children to this PSI element, after the specified anchor element. * - * @param first the first child element to add. - * @param last the last child element to add (must have the same parent as first) - * @param anchor the anchor after which the child element is inserted (must be a child of this PSI element) + * @param first the first child element to add. + * @param last the last child element to add (must have the same parent as first) + * @param anchor the anchor after which the child element is inserted (must be a child of this PSI element) * @return the first child element which was actually added (either first or its copy). * @throws IncorrectOperationException if the modification is not supported or not possible for some reason. */ @@ -327,7 +337,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * Deletes this PSI element from the tree. * * @throws IncorrectOperationException if the modification is not supported - * or not possible for some reason (for example, the file containing the element is read-only). + * or not possible for some reason (for example, the file containing the element is read-only). */ void delete() throws IncorrectOperationException; @@ -382,7 +392,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * associated reference. * * @return the reference instance, or null if the PSI element does not have any - * associated references. + * associated references. */ @Nullable PsiReference getReference(); @@ -394,15 +404,16 @@ public interface PsiElement extends UserDataHolder, Iconable { * contains only one text fragment which acts as a reference but the reference has * multiple possible targets, {@link PsiPolyVariantReference} should be used instead * of returning multiple references. - * + *

* Actually, it's preferable to call {@link com.intellij.psi.PsiReferenceService#getReferences} instead * as it allows adding references by plugins when the element implements {@link com.intellij.psi.ContributedReferenceHost}. * * @return the array of references, or an empty array if the element has no associated - * references. + * references. * @see com.intellij.psi.PsiReferenceService#getReferences */ - @NotNull PsiReference[] getReferences(); + @NotNull + PsiReference[] getReferences(); /** * Returns a copyable user data object attached to this element. @@ -411,13 +422,14 @@ public interface PsiElement extends UserDataHolder, Iconable { * @return the user data object, or null if no such object is found in the current element. * @see #putCopyableUserData(com.intellij.openapi.util.Key, Object) */ - @Nullable T getCopyableUserData(Key key); + @Nullable + T getCopyableUserData(Key key); /** * Attaches a copyable user data object to this element. Copyable user data objects are copied * when the PSI elements are copied. * - * @param key the key for accessing the user data object. + * @param key the key for accessing the user data object. * @param value the user data object to attach. * @see #getCopyableUserData(com.intellij.openapi.util.Key) */ @@ -427,12 +439,12 @@ public interface PsiElement extends UserDataHolder, Iconable { * Passes the declarations contained in this PSI element and its children * for processing to the specified scope processor. * - * @param processor the processor receiving the declarations. + * @param processor the processor receiving the declarations. * @param state - * @param lastParent the child of this element has been processed during the previous - * step of the tree up walk (declarations under this element do not need - * to be processed again) - * @param place the original element from which the tree up walk was initiated. + * @param lastParent the child of this element has been processed during the previous + * step of the tree up walk (declarations under this element do not need + * to be processed again) + * @param place the original element from which the tree up walk was initiated. * @return true if the declaration processing should continue or false if it should be stopped. */ boolean processDeclarations(@NotNull PsiScopeProcessor processor, @@ -444,11 +456,12 @@ public interface PsiElement extends UserDataHolder, Iconable { * Returns the element which should be used as the parent of this element in a tree up * walk during a resolve operation. For most elements, this returns getParent(), * but the context can be overridden for some elements like code fragments (see - * {@link PsiElementFactory#createCodeBlockCodeFragment(String, PsiElement, boolean)}). + * {@link PsiElementFactory#createCodeBlockCodeFragment(String, PsiElement, boolean)}). * * @return the resolve context element. */ - @Nullable PsiElement getContext(); + @Nullable + PsiElement getContext(); /** * Checks if an actual source or class file corresponds to the element. Non-physical elements include, @@ -465,7 +478,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the resolve scope instance. */ - @NotNull GlobalSearchScope getResolveScope(); + @NotNull + GlobalSearchScope getResolveScope(); /** * Returns the scope in which references to this element are searched. @@ -473,7 +487,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * @return the search scope instance. * @see {@link com.intellij.psi.search.PsiSearchHelper#getUseScope(PsiElement)} */ - @NotNull SearchScope getUseScope(); + @NotNull + SearchScope getUseScope(); /** * Returns the AST node corresponding to the element. @@ -485,7 +500,8 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * toString() should never be presented to the user. */ - @NonNls String toString(); + @NonNls + String toString(); boolean isEquivalentTo(PsiElement another); } diff --git a/platform/icons/src/process/fs/step_1.png b/platform/icons/src/process/fs/step_1.png new file mode 100644 index 000000000000..eb6c407124be Binary files /dev/null and b/platform/icons/src/process/fs/step_1.png differ diff --git a/platform/icons/src/process/fs/step_10.png b/platform/icons/src/process/fs/step_10.png new file mode 100644 index 000000000000..39aed3098195 Binary files /dev/null and b/platform/icons/src/process/fs/step_10.png differ diff --git a/platform/icons/src/process/fs/step_11.png b/platform/icons/src/process/fs/step_11.png new file mode 100644 index 000000000000..3b5e3ac43e1a Binary files /dev/null and b/platform/icons/src/process/fs/step_11.png differ diff --git a/platform/icons/src/process/fs/step_12.png b/platform/icons/src/process/fs/step_12.png new file mode 100644 index 000000000000..31c891386732 Binary files /dev/null and b/platform/icons/src/process/fs/step_12.png differ diff --git a/platform/icons/src/process/fs/step_13.png b/platform/icons/src/process/fs/step_13.png new file mode 100644 index 000000000000..02210fd7087f Binary files /dev/null and b/platform/icons/src/process/fs/step_13.png differ diff --git a/platform/icons/src/process/fs/step_14.png b/platform/icons/src/process/fs/step_14.png new file mode 100644 index 000000000000..35e5608db548 Binary files /dev/null and b/platform/icons/src/process/fs/step_14.png differ diff --git a/platform/icons/src/process/fs/step_15.png b/platform/icons/src/process/fs/step_15.png new file mode 100644 index 000000000000..96456a5122a6 Binary files /dev/null and b/platform/icons/src/process/fs/step_15.png differ diff --git a/platform/icons/src/process/fs/step_16.png b/platform/icons/src/process/fs/step_16.png new file mode 100644 index 000000000000..36be132b3918 Binary files /dev/null and b/platform/icons/src/process/fs/step_16.png differ diff --git a/platform/icons/src/process/fs/step_17.png b/platform/icons/src/process/fs/step_17.png new file mode 100644 index 000000000000..bf4f3b9ec5b8 Binary files /dev/null and b/platform/icons/src/process/fs/step_17.png differ diff --git a/platform/icons/src/process/fs/step_18.png b/platform/icons/src/process/fs/step_18.png new file mode 100644 index 000000000000..233501cadb81 Binary files /dev/null and b/platform/icons/src/process/fs/step_18.png differ diff --git a/platform/icons/src/process/fs/step_2.png b/platform/icons/src/process/fs/step_2.png new file mode 100644 index 000000000000..6c0aa8bb802f Binary files /dev/null and b/platform/icons/src/process/fs/step_2.png differ diff --git a/platform/icons/src/process/fs/step_3.png b/platform/icons/src/process/fs/step_3.png new file mode 100644 index 000000000000..bd3ed3da1858 Binary files /dev/null and b/platform/icons/src/process/fs/step_3.png differ diff --git a/platform/icons/src/process/fs/step_4.png b/platform/icons/src/process/fs/step_4.png new file mode 100644 index 000000000000..c7b463f0662e Binary files /dev/null and b/platform/icons/src/process/fs/step_4.png differ diff --git a/platform/icons/src/process/fs/step_5.png b/platform/icons/src/process/fs/step_5.png new file mode 100644 index 000000000000..a58da6614372 Binary files /dev/null and b/platform/icons/src/process/fs/step_5.png differ diff --git a/platform/icons/src/process/fs/step_6.png b/platform/icons/src/process/fs/step_6.png new file mode 100644 index 000000000000..3838816d288f Binary files /dev/null and b/platform/icons/src/process/fs/step_6.png differ diff --git a/platform/icons/src/process/fs/step_7.png b/platform/icons/src/process/fs/step_7.png new file mode 100644 index 000000000000..aeef1d044d40 Binary files /dev/null and b/platform/icons/src/process/fs/step_7.png differ diff --git a/platform/icons/src/process/fs/step_8.png b/platform/icons/src/process/fs/step_8.png new file mode 100644 index 000000000000..06d4602e9071 Binary files /dev/null and b/platform/icons/src/process/fs/step_8.png differ diff --git a/platform/icons/src/process/fs/step_9.png b/platform/icons/src/process/fs/step_9.png new file mode 100644 index 000000000000..c4a3766def38 Binary files /dev/null and b/platform/icons/src/process/fs/step_9.png differ diff --git a/platform/icons/src/process/fs/step_mask.png b/platform/icons/src/process/fs/step_mask.png new file mode 100644 index 000000000000..5411860022fe Binary files /dev/null and b/platform/icons/src/process/fs/step_mask.png differ diff --git a/platform/icons/src/process/fs/step_passive.png b/platform/icons/src/process/fs/step_passive.png new file mode 100644 index 000000000000..70d281bbc1b6 Binary files /dev/null and b/platform/icons/src/process/fs/step_passive.png differ diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java index c944eec2ffb4..454e396c268a 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java @@ -35,7 +35,7 @@ import java.awt.event.MouseEvent; import java.lang.ref.WeakReference; public class LineMarkerInfo { - private final Icon myIcon; + protected final Icon myIcon; private final WeakReference elementRef; public final int startOffset; public final int endOffset; @@ -157,7 +157,7 @@ public class LineMarkerInfo { return myInfo.myIconAlignment; } - private boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { + protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { return myInfo.getElement() != null && renderer.myInfo.getElement() != null && diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java index 9889bdf263a8..55ce601e8943 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java @@ -60,4 +60,27 @@ public class RelatedItemLineMarkerInfo extends LineMarkerI public Collection createGotoRelatedItems() { return myTargets.getValue(); } + + @Override + public GutterIconRenderer createGutterRenderer() { + if (myIcon == null) return null; + return new RelatedItemLineMarkerGutterIconRenderer(this); + } + + private static class RelatedItemLineMarkerGutterIconRenderer extends LineMarkerGutterIconRenderer { + public RelatedItemLineMarkerGutterIconRenderer(final RelatedItemLineMarkerInfo markerInfo) { + super(markerInfo); + } + + @Override + protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { + if (!(renderer instanceof RelatedItemLineMarkerGutterIconRenderer) || !super.looksTheSameAs(renderer)) { + return false; + } + + final RelatedItemLineMarkerInfo markerInfo = (RelatedItemLineMarkerInfo)getLineMarkerInfo(); + final RelatedItemLineMarkerInfo otherInfo = (RelatedItemLineMarkerInfo)renderer.getLineMarkerInfo(); + return markerInfo.myTargets.equals(otherInfo.myTargets); + } + } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java index 15b366e17909..946e31137556 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java @@ -51,7 +51,8 @@ public interface IntentionAction { * @return the intention family ID. * @see IntentionManager#registerIntentionAndMetaData(com.intellij.codeInsight.intention.IntentionAction, java.lang.String...) */ - @NotNull String getFamilyName(); + @NotNull + String getFamilyName(); /** * Checks whether this intention is available at a caret offset in file. diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java index 453b022dc298..6967f36ecb86 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java @@ -43,16 +43,17 @@ public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction throw new IncorrectOperationException(); } + @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { final PsiElement element = getElement(editor, file); return element != null && isAvailable(project, editor, element); } @Nullable - protected static PsiElement getElement(Editor editor, PsiFile file) { + protected static PsiElement getElement(Editor editor, @NotNull PsiFile file) { if (!file.getManager().isInProject(file)) return null; - final CaretModel caretModel = editor.getCaretModel(); - final int position = caretModel.getOffset(); + CaretModel caretModel = editor.getCaretModel(); + int position = caretModel.getOffset(); return file.findElementAt(position); } diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java index 31c89570a388..81d3d9a245dc 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull; public abstract class BaseIntentionAction implements IntentionAction { private String myText = ""; + @Override @NotNull public String getText() { return myText; @@ -34,6 +35,7 @@ public abstract class BaseIntentionAction implements IntentionAction { myText = text; } + @Override public boolean startInWriteAction() { return true; } diff --git a/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java b/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java index 4bbd1f3aaae2..d6c712357565 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java +++ b/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java @@ -54,8 +54,11 @@ public interface ModifiableModel extends Profile { void setModified(final boolean toolsSettingsChanged); + @Deprecated boolean isProperSetting(HighlightDisplayKey key); + boolean isProperSetting(String toolId); + void resetToBase(); void resetToEmpty(); @@ -66,8 +69,6 @@ public interface ModifiableModel extends Profile { void copyFrom(InspectionProfile profile); - boolean isDefault(); - void setEditable(String toolDisplayName); void save() throws IOException; diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java index bc558a8e2667..3f69ade8052a 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ public abstract class SdkType { private final String myName; /** - * @return path to set up filechooser to or null if not applicable + * @return path to set up file chooser to or null if not applicable */ @Nullable public abstract String suggestHomePath(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java index 00d0e8345a60..822e68e24e21 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java @@ -111,8 +111,9 @@ public class DaemonTooltipRendererProvider implements ErrorStripTooltipRendererP return new MyRenderer(text, width, new Object[] {text}); } + @NotNull @Override - public TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor) { + public TrafficTooltipRenderer createTrafficTooltipRenderer(@NotNull Runnable onHide, @NotNull Editor editor) { return new TrafficTooltipRendererImpl(onHide, editor); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index 4d01d1451764..f153046f4b0d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon.impl; +import com.google.common.primitives.Ints; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -265,7 +266,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator id2Pass = new TIntObjectHashMap(); final TIntArrayList passesRefusedToCreate = new TIntArrayList(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java index d34cb067fbf9..7818e095e0cf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java @@ -108,7 +108,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { private void refresh() { int maxIndex = mySeverityRegistrar.getSeverityMaxIndex(); if (errorCount != null && maxIndex == errorCount.length) return; - int[] newErrors = new int[maxIndex]; + int[] newErrors = new int[maxIndex+1]; if (errorCount != null) { System.arraycopy(errorCount, 0, newErrors, 0, Math.min(errorCount.length, newErrors.length)); } @@ -140,7 +140,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { HighlightSeverity infoSeverity = info.getSeverity(); final int severityIdx = mySeverityRegistrar.getSeverityIdx(infoSeverity); if (severityIdx != -1) { - errorCount[severityIdx]+= delta; + errorCount[severityIdx] += delta; } } 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 9cd4000274db..23915b48aedc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -718,6 +718,7 @@ public class DocumentationManager { myUpdateDocAlarm.addRequest(new Runnable() { public void run() { + if (myProject.isDisposed()) return; final Throwable[] ex = new Throwable[1]; String text = null; try { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java index 4b65a2c9716c..d2a99b30e253 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -379,7 +379,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser // Algorithm: the main idea is to process the first line of the pasted block, adjust its indent if necessary, calculate indent // adjustment string and apply to each line of the pasted block starting from the second one. // - // We differentiate three possible states here: + // We differentiate the following possible states here: // --- pasted block doesn't start new line, i.e. there are non-white space symbols before it at the first line. // Example: // old content [pasted line 1 @@ -460,7 +460,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser final int i = CharArrayUtil.shiftBackward(chars, startOffset - 1, " \t"); - // Handle situation when pasted block doesn't start new line. + // Handle a situation when pasted block doesn't start a new line. if (chars.charAt(startOffset) != '\n' && i > 0 && chars.charAt(i) != '\n') { int firstNonWsOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t"); if (firstNonWsOffset > firstLineStart) { @@ -550,7 +550,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser } } else { - CharSequence toInsert = chars.subSequence(anchorLineStart, j + diff); + CharSequence toInsert = chars.subSequence(anchorLineStart, diff + startOffset); for (int line = anchorLine + 1; line <= lastLine; line++) { document.insertString(document.getLineStartOffset(line), toInsert); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java index d87e82a67b38..a233872b8e6c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java @@ -131,7 +131,6 @@ class MoverWrapper { } }); } - CodeFoldingManager.getInstance(project).allowFoldingOnCaretLine(editor); if (hasSelection) { restoreSelection(editor, selectionStart, selectionEnd, start, myInfo.range2.getStartOffset()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java index be52c03fed31..7c9ed482d819 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java @@ -50,14 +50,4 @@ public abstract class CodeFoldingManager { public abstract void releaseFoldings(Editor editor); public abstract void buildInitialFoldings(Editor editor); - - /** - * Asks do not perform automatic expansion of fold region that is located on the caret line during the next fold regions update. - *

- * This method is necessary because fold regions that are located on caret line are automatically expanded to prevent problem - * from IDEA-64687. However, we don't want such an expansion when we, for example, move method up or down. - * - * @param editor target editor - */ - public abstract void allowFoldingOnCaretLine(@NotNull Editor editor); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java index f2008c380b8f..74c83d50d8cb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java @@ -331,9 +331,4 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec document.putUserData(FOLDING_STATE_INFO_IN_DOCUMENT_KEY, null); } } - - @Override - public void allowFoldingOnCaretLine(@NotNull Editor editor) { - editor.putUserData(UpdateFoldRegionsOperation.ALLOW_FOLDING_ON_CARET_LINE_KEY, true); - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java index e2e051772a6c..3ad2f94584a3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java @@ -18,14 +18,12 @@ package com.intellij.codeInsight.folding.impl; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.lang.injection.InjectedLanguageManager; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -43,9 +41,6 @@ import static com.intellij.util.containers.CollectionFactory.newTroveMap; * @author cdr */ class UpdateFoldRegionsOperation implements Runnable { - - static final Key ALLOW_FOLDING_ON_CARET_LINE_KEY = Key.create("AllowFoldingOnCaretLine.KEY"); - private final Project myProject; private final Editor myEditor; private final PsiFile myFile; @@ -80,9 +75,6 @@ class UpdateFoldRegionsOperation implements Runnable { List newRegions = addNewRegions(info, foldingModel, rangeToExpandStatusMap, shouldExpand, groupExpand); applyExpandStatus(newRegions, shouldExpand, groupExpand); - - // Reset the key. - myEditor.putUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY, false); } private static void applyExpandStatus(@NotNull List newRegions, @@ -147,24 +139,9 @@ class UpdateFoldRegionsOperation implements Runnable { // Considering that this code is executed only on initial fold regions construction on editor opening. return !FoldingPolicy.isCollapseByDefault(element); } - boolean caretInside; - if (myEditor.getUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY) == Boolean.TRUE) { - caretInside = FoldingUtil.caretInsideRange(myEditor, range); - } - else { - final Document document = myEditor.getDocument(); - final int firstLine = document.getLineNumber(range.getStartOffset()); - final int lastLine = document.getLineNumber(range.getEndOffset()); - int caretOffset = myEditor.getCaretModel().getOffset(); - if (caretOffset > myEditor.getDocument().getTextLength()) { - return false; - } - final int currentLine = document.getLineNumber(caretOffset); - caretInside = firstLine <= currentLine && currentLine <= lastLine; - } final Boolean oldStatus = rangeToExpandStatusMap.get(range); - return oldStatus == null || caretInside || oldStatus.booleanValue(); + return oldStatus == null || FoldingUtil.caretInsideRange(myEditor, range) || oldStatus.booleanValue(); } private void removeInvalidRegions(@NotNull EditorFoldingInfo info, diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java index a9b2ce6a04e9..8f3d92c65875 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java @@ -18,14 +18,13 @@ package com.intellij.codeInspection.ex; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.search.scope.packageSet.NamedScope; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * User: anna @@ -35,26 +34,20 @@ public class Descriptor { private final String myText; private final String[] myGroup; private final HighlightDisplayKey myKey; - - private final Element myConfig; + + private Element myConfig; private final InspectionProfileEntry myTool; private final HighlightDisplayLevel myLevel; private boolean myEnabled = false; private final NamedScope myScope; private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.Descriptor"); private final ScopeToolState myState; + private final InspectionProfileImpl myInspectionProfile; - public Descriptor(ScopeToolState pair, InspectionProfile inspectionProfile) { + public Descriptor(ScopeToolState pair, InspectionProfileImpl inspectionProfile) { myState = pair; + myInspectionProfile = inspectionProfile; final InspectionProfileEntry tool = pair.getTool(); - @NonNls Element config = new Element("options"); - try { - tool.writeSettings(config); - } - catch (WriteExternalException e) { - LOG.error(e); - } - myConfig = config; myText = tool.getDisplayName(); final String[] groupPath = tool.getGroupPath(); myGroup = groupPath.length == 0 ? new String[]{InspectionProfileEntry.GENERAL_GROUP_NAME} : groupPath; @@ -100,8 +93,7 @@ public class Descriptor { return myLevel; } - - + @Nullable public Element getConfig() { return myConfig; } @@ -110,11 +102,31 @@ public class Descriptor { return myTool; } + @Nullable public String loadDescription() { + if (myConfig == null) { + myConfig = createConfigElement(getTool()); + } + if (!(myTool instanceof InspectionTool)) return null; return myTool.loadDescription(); } + public InspectionProfileImpl getInspectionProfile() { + return myInspectionProfile; + } + + public static Element createConfigElement(InspectionProfileEntry tool) { + Element element = new Element("options"); + try { + tool.writeSettings(element); + } + catch (WriteExternalException e) { + LOG.error(e); + } + return element; + } + public String[] getGroup() { return myGroup; } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index ac35d14d2cc4..1f6f52be9fb4 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -206,6 +206,10 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G myContent.setDisposer(myView); + ContentManager contentManager = getContentManager(); + contentManager.addContent(myContent); + contentManager.setSelectedContent(myContent); + ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.INSPECTION).activate(null); } @@ -631,8 +635,7 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G } protected List getUsedTools() { - final InspectionProfileImpl profile = new InspectionProfileImpl((InspectionProfileImpl)getCurrentProfile()); - return profile.getAllEnabledInspectionTools(myProject); + return ((InspectionProfileImpl)getCurrentProfile()).getAllEnabledInspectionTools(myProject); } private void classifyTool(List outGlobalTools, diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java index 6cbbba6a4c2b..b79c4338312d 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java @@ -32,6 +32,7 @@ import com.intellij.openapi.options.ExternalizableScheme; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.profile.ApplicationProfileManager; @@ -93,7 +94,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, private boolean myModified = false; private volatile boolean myInitialized; - public InspectionProfileImpl(InspectionProfileImpl inspectionProfile) { + private InspectionProfileImpl(@NotNull InspectionProfileImpl inspectionProfile) { super(inspectionProfile.getName()); myRegistrar = inspectionProfile.myRegistrar; @@ -168,20 +169,19 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, final ToolsImpl toolList1 = profile1.myTools.get(toolName); final ToolsImpl toolList2 = profile2.myTools.get(toolName); - return toolList1 == null && toolList2 == null || toolList1 != null && toolList2 != null && toolList1.equalTo(toolList2); + return Comparing.equal(toolList1, toolList2); } + @Override public boolean isProperSetting(HighlightDisplayKey key) { - final Map diffMap = getDisplayLevelMap(); - if (diffMap != null) { - final ToolsImpl tools = myBaseProfile.getTools(key.toString()); - final ToolsImpl currentTools = myTools.get(key.toString()); - if (tools != null && currentTools != null) { - diffMap.put(key.toString(), tools.equalTo(currentTools)); - } else { - diffMap.put(key.toString(), tools == currentTools); - } - return !diffMap.get(key.toString()).booleanValue(); + return isProperSetting(key.toString()); + } + + public boolean isProperSetting(String toolId) { + if (myBaseProfile != null) { + final ToolsImpl tools = myBaseProfile.getTools(toolId); + final ToolsImpl currentTools = myTools.get(toolId); + return !Comparing.equal(tools, currentTools); } return false; } @@ -376,27 +376,11 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, } } - public boolean isDefault() { - final Map map = getDisplayLevelMap(); - if (map != null) { - for (Boolean def : map.values()) { - if (!def.booleanValue()) return false; - } - } - return true; - } - public boolean isProfileLocked() { return myLockedProfile; } public void lockProfile(boolean isLocked) { - for (Tools toolList : myTools.values()) { - final String key = toolList.getShortName(); - if (isLocked) { - myDisplayLevelMap.put(key, Boolean.FALSE); - } - } myLockedProfile = isLocked; } @@ -490,16 +474,13 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, } myTools.put(tool.getShortName(), toolsList); } - if (mySource != null) { - copyToolsConfigurations(mySource, project); - } return true; } private HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key) { final ToolsImpl tools = getTools(key.toString()); LOG.assertTrue(tools != null, "profile name: " + myName + " base profile: " + (myBaseProfile != null ? myBaseProfile.getName() : "-") + " key: " + key); - return tools != null ? tools.getLevel() : HighlightDisplayLevel.WARNING; + return tools.getLevel(); } @NotNull @@ -807,4 +788,8 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, disableTool(entry.getShortName()); } } + + public String toString() { + return mySource == null ? getName() : getName() + " (copy)"; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java index 9e7285436365..9f1435366b3a 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java @@ -150,35 +150,40 @@ public class ToolsImpl implements Tools { final String enabledTool = toolElement.getAttributeValue(ENABLED_TAG); myDefaultState.setEnabled(enabledTool != null ? Boolean.parseBoolean(enabledTool) : isEnabled); final InspectionToolWrapper tool = (InspectionToolWrapper)myDefaultState.getTool(); - tool.readSettings(toolElement); + final List children = toolElement.getChildren(InspectionProfileImpl.SCOPE); - if (!children.isEmpty()) { - for (Object sO : children) { - final Element scopeElement = (Element)sO; - final String scopeName = scopeElement.getAttributeValue(InspectionProfileImpl.NAME); - if (scopeName != null) { - final NamedScopesHolder scopesHolder = profileManager.getScopesManager(); - NamedScope namedScope = null; - if (scopesHolder != null) { - namedScope = scopesHolder.getScope(scopeName); - } - final String errorLevel = scopeElement.getAttributeValue(InspectionProfileImpl.LEVEL_TAG); - final String enabledInScope = scopeElement.getAttributeValue(InspectionProfileImpl.ENABLED_TAG); - final InspectionProfileEntry copyTool = tool.createCopy(tool); - copyTool.readSettings(scopeElement); - HighlightDisplayLevel scopeLevel = errorLevel != null ? - HighlightDisplayLevel.find(((SeverityProvider)profileManager).getOwnSeverityRegistrar().getSeverity(errorLevel)) : null; - if (scopeLevel == null) { - scopeLevel = level; - } - if (namedScope != null) { - addTool(namedScope, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); - } else { - addTool(scopeName, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); - } + for (Object sO : children) { + final Element scopeElement = (Element)sO; + final String scopeName = scopeElement.getAttributeValue(InspectionProfileImpl.NAME); + if (scopeName != null) { + final NamedScopesHolder scopesHolder = profileManager.getScopesManager(); + NamedScope namedScope = null; + if (scopesHolder != null) { + namedScope = scopesHolder.getScope(scopeName); + } + final String errorLevel = scopeElement.getAttributeValue(InspectionProfileImpl.LEVEL_TAG); + final String enabledInScope = scopeElement.getAttributeValue(InspectionProfileImpl.ENABLED_TAG); + final InspectionProfileEntry copyTool = tool.createCopy(tool); + copyTool.readSettings(scopeElement); + HighlightDisplayLevel scopeLevel = errorLevel != null ? + HighlightDisplayLevel + .find(((SeverityProvider)profileManager).getOwnSeverityRegistrar().getSeverity(errorLevel)) + : null; + if (scopeLevel == null) { + scopeLevel = level; + } + if (namedScope != null) { + addTool(namedScope, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); + } + else { + addTool(scopeName, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); } } } + +// if (toolElement.getAttributes().size() > 4 || toolElement.getChildren().size() > children.size()) { + tool.readSettings(toolElement); +// } } public ScopeToolState addTool(String scopeName, InspectionProfileEntry tool, boolean enabled, HighlightDisplayLevel level) { @@ -386,7 +391,8 @@ public class ToolsImpl implements Tools { return myDefaultState.getLevel(); } - public boolean equalTo(ToolsImpl tools) { + public boolean equals(Object o) { + ToolsImpl tools = (ToolsImpl)o; if (myEnabled != tools.myEnabled) return false; if (getTools().size() != tools.getTools().size()) return false; for (int i = 0; i < getTools().size(); i++) { diff --git a/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java b/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java index 769a71783136..6b6f39b78565 100644 --- a/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java +++ b/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java @@ -64,4 +64,6 @@ public interface ConversionContext { ProjectLibrariesSettings getProjectLibrariesSettings() throws CannotConvertException; + @NotNull + String expandPath(@NotNull String path); } diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java index ed0e38983de7..21b27fc5a113 100644 --- a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java @@ -159,6 +159,13 @@ public class ConversionContextImpl implements ConversionContext { return map; } + @Override + @NotNull + public String expandPath(@NotNull String path) { + ExpandMacroToPathMap map = createExpandMacroMap(null); + return map.substitute(path, SystemInfo.isFileSystemCaseSensitive); + } + @NotNull public String collapsePath(@NotNull String path) { ReplacePathToMacroMap map = createCollapseMacroMap(PathMacrosImpl.PROJECT_DIR_MACRO_NAME, myProjectBaseDir); diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 1be5c6ccf3c9..71b22aef2b5c 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -95,6 +95,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { private final JPanel myPanel = new JPanel(new MyLayout()); private String myTitle; + @Nullable private String myPrompt = "> "; private final LightVirtualFile myHistoryFile; private Editor myCurrentEditor; @@ -316,11 +317,12 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { return myHistoryFile; } + @Nullable public String getPrompt() { return myPrompt; } - public void setPrompt(String prompt) { + public void setPrompt(@Nullable String prompt) { // always add space to the prompt otherwise it may look ugly myPrompt = prompt != null && !prompt.endsWith(" ") ? prompt + " " : prompt; setPromptInner(myPrompt); @@ -435,8 +437,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { protected String addTextRangeToHistory(TextRange textRange, final EditorEx consoleEditor, boolean preserveMarkup) { final Document history = myHistoryViewer.getDocument(); final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true); - appendToHistoryDocument(history, myPrompt); - markupModel.addRangeHighlighter(history.getTextLength() - myPrompt.length(), history.getTextLength(), HighlighterLayer.SYNTAX, + if (myPrompt != null) { + appendToHistoryDocument(history, myPrompt); + } + markupModel.addRangeHighlighter(history.getTextLength() - StringUtil.length(myPrompt), history.getTextLength(), HighlighterLayer.SYNTAX, ConsoleViewContentType.USER_INPUT.getAttributes(), HighlighterTargetArea.EXACT_RANGE); diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java index 0b5249e6757e..03c5c8592feb 100644 --- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java @@ -1,14 +1,9 @@ package com.intellij.find.editorHeaderActions; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.vfs.ReadonlyStatusHandler; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; import javax.swing.*; import javax.swing.text.JTextComponent; @@ -42,7 +37,7 @@ public class Utils { .setRequestFocus(true).setItemChoosenCallback(callback).createPopup(); if (ad != null) { - popup.setAdText(ad, SwingUtilities.LEFT); + popup.setAdText(ad, SwingConstants.LEFT); } if (toolbarComponent != null) { @@ -72,20 +67,4 @@ public class Utils { } } } - - public static boolean ensureOkToWrite(Editor e) { - final PsiFile psiFile = PsiDocumentManager.getInstance(e.getProject()).getPsiFile(e.getDocument()); - boolean okWritable; - if (psiFile != null) { - final VirtualFile virtualFile = psiFile.getVirtualFile(); - if (virtualFile != null) { - okWritable = ReadonlyStatusHandler.ensureFilesWritable(e.getProject(), virtualFile); - } else { - okWritable = psiFile.isWritable(); - } - } else { - okWritable = e.getDocument().isWritable(); - } - return okWritable; - } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java index a4d145e343bc..c746ee722c2f 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java @@ -3,13 +3,13 @@ package com.intellij.find.impl.livePreview; import com.intellij.find.FindManager; import com.intellij.find.FindModel; import com.intellij.find.FindUtil; -import com.intellij.find.editorHeaderActions.Utils; import com.intellij.find.impl.FindResultImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.util.Alarm; import org.jetbrains.annotations.Nullable; @@ -169,7 +169,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Nullable @Override public TextRange performReplace(final LiveOccurrence occurrence, final String replacement, final Editor editor) { - if (myReplaceDenied || !Utils.ensureOkToWrite(editor)) return null; + if (myReplaceDenied || !ReadonlyStatusHandler.ensureDocumentWritable(editor.getProject(), editor.getDocument())) return null; TextRange range = occurrence.getPrimaryRange(); FindModel findModel = mySearchResults.getFindModel(); TextRange result = null; @@ -197,7 +197,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Override public void performReplaceAll(Editor e) { - if (!Utils.ensureOkToWrite(e)) return; + if (!ReadonlyStatusHandler.ensureDocumentWritable(e.getProject(), e.getDocument())) return; if (mySearchResults.getFindModel() != null) { final FindModel copy = new FindModel(); copy.copyFrom(mySearchResults.getFindModel()); diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java index a94ac1a097e4..db019a2f0eda 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java @@ -26,6 +26,7 @@ import com.intellij.navigation.NavigationItem; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; 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.GutterIconRenderer; import com.intellij.openapi.editor.markup.HighlighterLayer; @@ -41,6 +42,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.ui.LightColors; import com.intellij.util.PlatformIcons; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,45 +54,41 @@ public class Bookmark { private final VirtualFile myFile; private final OpenFileDescriptor myTarget; - private final RangeHighlighter myHighlighter; private final Project myProject; private String myDescription; private char myMnemonic = 0; public static final Font MNEMONIC_FONT = new Font("Monospaced", 0, 11); - public Bookmark(Project project, VirtualFile file, String description) { - this(project, file, -1, description); - } - - public Bookmark(Project project, VirtualFile file, int line, String description) { + public Bookmark(@NotNull Project project, @NotNull VirtualFile file, int line, @NotNull String description) { myFile = file; myProject = project; myDescription = description; + myTarget = new OpenFileDescriptor(project, file, line, -1, true); + + Document document = FileDocumentManager.getInstance().getCachedDocument(getFile()); + if (document != null) { + createHighlighter((MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true)); + } + } + + public RangeHighlighter createHighlighter(@NotNull MarkupModelEx markup) { + final RangeHighlighter myHighlighter; + int line = getLine(); if (line >= 0) { - Document document = getDocument(); - if (document == null) { - myHighlighter = null; - } - else { - MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true); - myHighlighter = markup.addPersistentLineHighlighter(line, HighlighterLayer.ERROR + 1, null); + myHighlighter = markup.addPersistentLineHighlighter(line, HighlighterLayer.ERROR + 1, null); + if (myHighlighter != null) { + myHighlighter.setGutterIconRenderer(new MyGutterIconRenderer(this)); - - if (myHighlighter != null) { - myHighlighter.setGutterIconRenderer(new MyGutterIconRenderer()); - - myHighlighter.setErrorStripeMarkColor(Color.black); - myHighlighter.setErrorStripeTooltip(getBookmarkTooltip()); - } + myHighlighter.setErrorStripeMarkColor(Color.black); + myHighlighter.setErrorStripeTooltip(getBookmarkTooltip()); } } else { myHighlighter = null; } - - myTarget = new OpenFileDescriptor(project, file, line, -1, true); + return myHighlighter; } public Document getDocument() { @@ -98,9 +96,28 @@ public class Bookmark { } public void release() { - if (myHighlighter != null) { - myHighlighter.dispose(); + int line = getLine(); + if (line < 0) { + return; } + final Document document = getDocument(); + if (document == null) return; + MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true); + int startOffset = markup.getDocument().getLineStartOffset(line); + int endOffset = markup.getDocument().getLineEndOffset(line); + final RangeHighlighterEx[] found = new RangeHighlighterEx[1]; + markup.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor() { + @Override + public boolean process(RangeHighlighterEx highlighter) { + GutterIconRenderer renderer = highlighter.getGutterIconRenderer(); + if (renderer instanceof MyGutterIconRenderer && ((MyGutterIconRenderer)renderer).myBookmark == Bookmark.this) { + found[0] = highlighter; + return false; + } + return true; + } + }); + if (found[0] != null) found[0].dispose(); } public Icon getIcon() { @@ -123,25 +140,18 @@ public class Bookmark { myMnemonic = Character.toUpperCase(mnemonic); } + @NotNull public VirtualFile getFile() { return myFile; } @Nullable public String getNotEmptyDescription() { - return isDescriptionEmpty() ? null : myDescription; - } - - public boolean isDescriptionEmpty() { - return myDescription == null || myDescription.trim().length() == 0; - } - - OpenFileDescriptor getTarget() { - return myTarget; + return StringUtil.isEmpty(myDescription) ? null : myDescription; } public boolean isValid() { - if (!getFile().isValid() || (myHighlighter != null && !myHighlighter.isValid())) { + if (!getFile().isValid()) { return false; } @@ -156,8 +166,10 @@ public class Bookmark { } public int getLine() { - if (myHighlighter != null && myHighlighter.isValid()) { - return myHighlighter.getDocument().getLineNumber(myHighlighter.getStartOffset()); + RangeMarker marker = myTarget.getRangeMarker(); + if (marker != null && marker.isValid()) { + Document document = marker.getDocument(); + return document.getLineNumber(marker.getStartOffset()); } return myTarget.getLine(); } @@ -169,7 +181,7 @@ public class Bookmark { public String getQualifiedName() { String presentableUrl = myFile.getPresentableUrl(); - if (myFile.isDirectory() || myHighlighter == null) return presentableUrl; + if (myFile.isDirectory()) return presentableUrl; PsiDocumentManager.getInstance(myProject).commitAllDocuments(); final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(myFile); @@ -188,8 +200,7 @@ public class Bookmark { } } - return IdeBundle - .message("bookmark.file.X.line.Y", presentableUrl, myHighlighter.getDocument().getLineNumber(myHighlighter.getStartOffset()) + 1); + return IdeBundle.message("bookmark.file.X.line.Y", presentableUrl, getLine() + 1); } private String getBookmarkTooltip() { @@ -211,6 +222,7 @@ public class Bookmark { myMnemonic = mnemonic; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(LightColors.YELLOW); g.fillRect(x, y, getIconWidth(), getIconHeight()); @@ -226,10 +238,12 @@ public class Bookmark { g.setFont(oldFont); } + @Override public int getIconWidth() { return 10; } + @Override public int getIconHeight() { return 12; } @@ -245,14 +259,22 @@ public class Bookmark { } } - private class MyGutterIconRenderer extends GutterIconRenderer { - @NotNull - public Icon getIcon() { - return Bookmark.this.getIcon(); + private static class MyGutterIconRenderer extends GutterIconRenderer { + private final Bookmark myBookmark; + + public MyGutterIconRenderer(@NotNull Bookmark bookmark) { + myBookmark = bookmark; } + @Override + @NotNull + public Icon getIcon() { + return myBookmark.getIcon(); + } + + @Override public String getTooltipText() { - return getBookmarkTooltip(); + return myBookmark.getBookmarkTooltip(); } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java index 3e46735e892c..0d995bebeb7b 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java @@ -16,25 +16,32 @@ package com.intellij.ide.bookmarks; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.AbstractProjectComponent; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.*; +import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.impl.DocumentMarkupModel; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.util.messages.MessageBus; +import com.intellij.util.ui.UIUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.awt.*; import java.awt.event.InputEvent; import java.util.*; @@ -46,51 +53,54 @@ import java.util.List; @Storage( file = "$WORKSPACE_FILE$") } ) -public class BookmarkManager implements PersistentStateComponent, ProjectComponent { - +public class BookmarkManager extends AbstractProjectComponent implements PersistentStateComponent { private static final int MAX_AUTO_DESCRIPTION_SIZE = 50; - private final List myBookmarks = new ArrayList(); - private final MyEditorMouseListener myEditorMouseListener = new MyEditorMouseListener(); + private final List myBookmarks = new ArrayList(); - private final Project myProject; private final MessageBus myBus; public static BookmarkManager getInstance(Project project) { return project.getComponent(BookmarkManager.class); } - public BookmarkManager(Project project, MessageBus bus) { - myProject = project; + public BookmarkManager(Project project, MessageBus bus, PsiDocumentManager documentManager) { + super(project); myBus = bus; - EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new MyDocumentListener(), myProject); + EditorEventMulticaster multicaster = EditorFactory.getInstance().getEventMulticaster(); + multicaster.addDocumentListener(new MyDocumentListener(), myProject); + multicaster.addEditorMouseListener(new MyEditorMouseListener(), myProject); + + documentManager.addListener(new PsiDocumentManager.Listener() { + @Override + public void documentCreated(@NotNull final Document document, PsiFile psiFile) { + final VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null) return; + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (myProject.isDisposed()) return; + for (Bookmark bookmark : myBookmarks) { + if (bookmark.getFile() == file) { + bookmark.createHighlighter((MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true)); + } + } + } + }); + } + + @Override + public void fileCreated(@NotNull PsiFile file, @NotNull Document document) { + } + }); } - public void projectOpened() { - EditorFactory.getInstance().getEventMulticaster().addEditorMouseListener(myEditorMouseListener, myProject); - } - - @Override - public void projectClosed() { - EditorFactory.getInstance().getEventMulticaster().removeEditorMouseListener(myEditorMouseListener); - } - - @Override - public void initComponent() {} - - @Override - public void disposeComponent() {} - @NotNull @Override public String getComponentName() { return "BookmarkManager"; } - public Project getProject() { - return myProject; - } - public void addEditorBookmark(Editor editor, int lineIndex) { Document document = editor.getDocument(); PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document); @@ -127,7 +137,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje if (file == null) return null; if (findFileBookmark(file) != null) return null; - Bookmark b = new Bookmark(myProject, file, description); + Bookmark b = new Bookmark(myProject, file, -1, description); myBookmarks.add(0, b); myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkAdded(b); return b; @@ -144,9 +154,9 @@ public class BookmarkManager implements PersistentStateComponent, Proje @Nullable - public Bookmark findEditorBookmark(Document document, int lineIndex) { + public Bookmark findEditorBookmark(@NotNull Document document, int line) { for (Bookmark bookmark : myBookmarks) { - if (bookmark.getDocument() == document && bookmark.getLine() == lineIndex) { + if (bookmark.getDocument() == document && bookmark.getLine() == line) { return bookmark; } } @@ -155,7 +165,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje } @Nullable - public Bookmark findFileBookmark(VirtualFile file) { + public Bookmark findFileBookmark(@NotNull VirtualFile file) { for (Bookmark bookmark : myBookmarks) { if (bookmark.getFile() == file && bookmark.getLine() == -1) return bookmark; } @@ -180,20 +190,23 @@ public class BookmarkManager implements PersistentStateComponent, Proje return false; } - public void removeBookmark(Bookmark bookmark) { + public void removeBookmark(@NotNull Bookmark bookmark) { myBookmarks.remove(bookmark); bookmark.release(); myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkRemoved(bookmark); } + @Override public Element getState() { Element container = new Element("BookmarkManager"); writeExternal(container); return container; } + @Override public void loadState(final Element state) { StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { + @Override public void run() { BookmarksListener publisher = myBus.syncPublisher(BookmarksListener.TOPIC); for (Bookmark bookmark : myBookmarks) { @@ -214,7 +227,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje if ("bookmark".equals(bookmarkElement.getName())) { String url = bookmarkElement.getAttributeValue("url"); String line = bookmarkElement.getAttributeValue("line"); - String description = bookmarkElement.getAttributeValue("description"); + String description = StringUtil.notNullize(bookmarkElement.getAttributeValue("description")); String mnemonic = bookmarkElement.getAttributeValue("mnemonic"); Bookmark b = null; @@ -335,6 +348,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje Bookmark[] bookmarks = answer.toArray(new Bookmark[answer.size()]); Arrays.sort(bookmarks, new Comparator() { + @Override public int compare(final Bookmark o1, final Bookmark o2) { return o1.getLine() - o2.getLine(); } @@ -342,7 +356,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje return bookmarks; } - public void setMnemonic(Bookmark bookmark, char c) { + public void setMnemonic(@NotNull Bookmark bookmark, char c) { final Bookmark old = findBookmarkForMnemonic(c); if (old != null) removeBookmark(old); @@ -350,13 +364,14 @@ public class BookmarkManager implements PersistentStateComponent, Proje myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkChanged(bookmark); } - public void setDescription(Bookmark bookmark, String description) { + public void setDescription(@NotNull Bookmark bookmark, String description) { bookmark.setDescription(description); myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkChanged(bookmark); } private class MyEditorMouseListener extends EditorMouseAdapter { + @Override public void mouseClicked(final EditorMouseEvent e) { if (e.getArea() != EditorMouseEventArea.LINE_MARKERS_AREA) return; if (e.getMouseEvent().isPopupTrigger()) return; diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java index 398ba6ef72cb..ea052a27ad79 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java @@ -20,12 +20,13 @@ package com.intellij.ide.bookmarks; import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NotNull; public interface BookmarksListener { Topic TOPIC = Topic.create("Bookmarks", BookmarksListener.class); - void bookmarkAdded(Bookmark b); - void bookmarkRemoved(Bookmark b); + void bookmarkAdded(@NotNull Bookmark b); + void bookmarkRemoved(@NotNull Bookmark b); - void bookmarkChanged(Bookmark b); + void bookmarkChanged(@NotNull Bookmark b); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java index 83dc5f1c918f..6d2ef559b21a 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java @@ -64,8 +64,10 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { myPsiTreeChangeListener = createPsiTreeChangeListener(myProject); connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { + @Override public void beforeRootsChange(ModuleRootEvent event) { } + @Override public void rootsChanged(ModuleRootEvent event) { queueUpdate(); } @@ -87,6 +89,7 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { initRootNode(); } + @Override public final void dispose() { super.dispose(); PsiManager.getInstance(myProject).removePsiTreeChangeListener(myPsiTreeChangeListener); @@ -110,29 +113,35 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { super(project); } + @Override protected DefaultMutableTreeNode getRootNode(){ return ProjectTreeBuilder.this.getRootNode(); } + @Override protected AbstractTreeUpdater getUpdater() { return ProjectTreeBuilder.this.getUpdater(); } + @Override protected boolean isFlattenPackages(){ return ((AbstractProjectTreeStructure)getTreeStructure()).isFlattenPackages(); } } private final class MyBookmarksListener implements BookmarksListener { - public void bookmarkAdded(Bookmark b) { + @Override + public void bookmarkAdded(@NotNull Bookmark b) { updateForFile(b.getFile()); } - public void bookmarkRemoved(Bookmark b) { + @Override + public void bookmarkRemoved(@NotNull Bookmark b) { updateForFile(b.getFile()); } - public void bookmarkChanged(Bookmark b) { + @Override + public void bookmarkChanged(@NotNull Bookmark b) { updateForFile(b.getFile()); } @@ -145,10 +154,12 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { } private final class MyFileStatusListener implements FileStatusListener { + @Override public void fileStatusesChanged() { queueUpdate(false); } + @Override public void fileStatusChanged(@NotNull VirtualFile vFile) { queueUpdate(false); } @@ -171,10 +182,12 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { private final Alarm myUpdateProblemAlarm = new Alarm(); private final Collection myFilesToRefresh = new THashSet(); + @Override public void problemsAppeared(VirtualFile file) { queueUpdate(file); } + @Override public void problemsDisappeared(VirtualFile file) { queueUpdate(file); } @@ -184,6 +197,7 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { if (myFilesToRefresh.add(fileToRefresh)) { myUpdateProblemAlarm.cancelAllRequests(); myUpdateProblemAlarm.addRequest(new Runnable() { + @Override public void run() { if (!myProject.isOpen()) return; Set filesToRefresh; diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java b/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java index 624c8d643c4f..057beb6772be 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java @@ -7,6 +7,7 @@ import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.treeStructure.SimpleNode; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import java.awt.*; public class BlockTreeNode extends SimpleNode { @@ -56,6 +57,7 @@ public class BlockTreeNode extends SimpleNode { } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[]{myBlock}; diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java index 92d3cfa6a88b..2793909588ed 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java @@ -27,6 +27,7 @@ import com.intellij.ui.DeferredIconImpl; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.util.Function; import com.intellij.util.ui.update.ComparableObject; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -134,6 +135,7 @@ public class NativeFileIconProvider implements FileIconProvider { myText = new Object[] {text, flags}; } + @NotNull public Object[] getEqualityObjects() { return myText; } diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java index dbbbacc90f1d..90ad86b3980b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java @@ -29,6 +29,7 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -39,11 +40,9 @@ import java.util.Set; public class LibraryRuntimeClasspathScope extends GlobalSearchScope { private final ProjectFileIndex myIndex; private final LinkedHashSet myEntries = new LinkedHashSet(); - private final List myModules; public LibraryRuntimeClasspathScope(final Project project, final List modules) { super(project); - myModules = modules; myIndex = ProjectRootManager.getInstance(project).getFileIndex(); final Set processedSdk = new THashSet(); final Set processedLibraries = new THashSet(); @@ -63,8 +62,14 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope { } } + public LibraryRuntimeClasspathScope(Project project, LibraryOrderEntry entry) { + super(project); + myIndex = ProjectRootManager.getInstance(project).getFileIndex(); + Collections.addAll(myEntries, entry.getRootFiles(OrderRootType.CLASSES)); + } + public int hashCode() { - return myModules.hashCode(); + return myEntries.hashCode(); } public boolean equals(Object object) { @@ -72,7 +77,7 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope { if (object == null || object.getClass() != LibraryRuntimeClasspathScope.class) return false; final LibraryRuntimeClasspathScope that = (LibraryRuntimeClasspathScope)object; - return that.myModules.equals(myModules); + return that.myEntries.equals(myEntries); } private void buildEntries(@NotNull final Module module, diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java index 6090e7ab87ae..6c8dd4145c98 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java @@ -248,7 +248,7 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone DirectoryInfo info = stateAndDirs.first.myDirToInfoMap.get(dir); assert info != null; - if (!info.isInLibrarySource || info.libraryClassRoot != null) { + if (!info.isInLibrarySource || info.isInModuleSource || info.libraryClassRoot != null) { if (!consumer.process(dir)) return false; } } @@ -613,7 +613,6 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone if (definedPackage != null && definedPackage.isEmpty()) return; // another library source root starts here } - info.isInModuleSource = false; info.isInLibrarySource = true; info.sourceRoot = sourceRoot; setPackageName(dir, packageName); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java index 1b90c18bfe4c..9eb223dff4ed 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java @@ -40,6 +40,8 @@ import com.intellij.openapi.roots.ui.configuration.actions.ToggleExcludedStateAc import com.intellij.openapi.roots.ui.configuration.actions.ToggleSourcesStateAction; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.TreeSpeedSearch; @@ -144,8 +146,11 @@ public class ContentEntryTreeEditor { final ContentEntry entry = contentEntryEditor.getContentEntry(); assert entry != null : contentEntryEditor; final VirtualFile file = entry.getFile(); - assert file != null : entry.getUrl(); myDescriptor.setRoots(file); + if (file == null) { + final String path = VfsUtil.urlToPath(entry.getUrl()); + myDescriptor.setTitle(FileUtil.toSystemDependentName(path)); + } final Runnable init = new Runnable() { public void run() { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java index ea28984c6757..4b4ca429d416 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java @@ -67,9 +67,15 @@ public class ModulesCombobox extends ComboBox { } public void fillModules(@NotNull Project project) { + fillModules(project, null); + } + + public void fillModules(@NotNull Project project, final @Nullable ModuleType moduleType) { myModel.clear(); for (Module module : ModuleManager.getInstance(project).getModules()) { - myModel.add(module); + if (moduleType == null || moduleType.equals(ModuleType.get(module))) { + myModel.add(module); + } } } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java index 339f0a2ae9bf..9b22317381e7 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java @@ -22,30 +22,45 @@ package com.intellij.profile.codeInspection.ui; import com.intellij.codeInspection.ex.Descriptor; import com.intellij.codeInspection.ex.ScopeToolState; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.psi.search.scope.packageSet.NamedScope; import com.intellij.ui.CheckedTreeNode; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class InspectionConfigTreeNode extends CheckedTreeNode { private ScopeToolState myState; private boolean myByDefault; private boolean myInspectionNode; - public boolean isProperSetting; + private final NotNullLazyValue myProperSetting = new NotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + Descriptor descriptor = getDesriptor(); + if (descriptor != null) return descriptor.getInspectionProfile().isProperSetting(descriptor.getTool().getShortName()); + for (int i = 0; i < getChildCount(); i++) { + InspectionConfigTreeNode node = (InspectionConfigTreeNode)getChildAt(i); + if (node.isProperSetting()) { + return true; + } + } + return false; + } + }; - public InspectionConfigTreeNode(Object userObject, ScopeToolState state, boolean byDefault, boolean properSetting, boolean inspectionNode) { + public InspectionConfigTreeNode(Object userObject, ScopeToolState state, boolean byDefault, boolean inspectionNode) { super(userObject); myState = state; myByDefault = byDefault; - isProperSetting = properSetting; myInspectionNode = inspectionNode; if (state != null) { setChecked(state.isEnabled()); } } - public InspectionConfigTreeNode(Descriptor descriptor, ScopeToolState state, boolean byDefault, boolean isEnabled, boolean properSetting, + public InspectionConfigTreeNode(Descriptor descriptor, ScopeToolState state, boolean byDefault, boolean isEnabled, boolean inspectionNode) { - this(descriptor, state, byDefault, properSetting, inspectionNode); + this(descriptor, state, byDefault, inspectionNode); setChecked(isEnabled); } @@ -85,4 +100,12 @@ public class InspectionConfigTreeNode extends CheckedTreeNode { public String getScopeName() { return myState != null ? myState.getScopeName() : null; } + + public boolean isProperSetting() { + return myProperSetting.getValue(); + } + + public void dropCache() { + myProperSetting.drop(); + } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java index 1fd982b5c461..dfacaad3b06d 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java @@ -53,7 +53,7 @@ abstract class InspectionsConfigTreeRenderer extends CheckboxTree.CheckboxTreeCe final Color background = selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground(); UIUtil.changeBackGround(this, background); Color foreground = - selected ? UIUtil.getTreeSelectionForeground() : node.isProperSetting ? Color.BLUE : UIUtil.getTreeTextForeground(); + selected ? UIUtil.getTreeSelectionForeground() : node.isProperSetting() ? Color.BLUE : UIUtil.getTreeTextForeground(); @NonNls String text = null; int style = SimpleTextAttributes.STYLE_PLAIN; diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 3fd374b320bf..3010f8fa3d08 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -46,7 +46,6 @@ import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; import com.intellij.profile.ProfileManager; import com.intellij.profile.codeInspection.InspectionProfileManager; @@ -101,7 +100,7 @@ public class SingleInspectionProfilePanel extends JPanel { private JPanel myInspectionProfilePanel = null; private FilterComponent myProfileFilter; private final InspectionConfigTreeNode myRoot = - new InspectionConfigTreeNode(InspectionsBundle.message("inspection.root.node.title"), null, false, false, false); + new InspectionConfigTreeNode(InspectionsBundle.message("inspection.root.node.title"), null, false, false); private final Alarm myAlarm = new Alarm(); private boolean myModified = false; private Tree myTree; @@ -187,13 +186,8 @@ public class SingleInspectionProfilePanel extends JPanel { return false; } Element oldConfig = descriptor.getConfig(); - @NonNls Element newConfig = new Element("options"); - try { - tool.writeSettings(newConfig); - } - catch (WriteExternalException e) { - LOG.error(e); - } + if (oldConfig == null) return false; + Element newConfig = Descriptor.createConfigElement(tool); if (!JDOMUtil.areElementsEqual(oldConfig, newConfig)) { myAlarm.cancelAllRequests(); myAlarm.addRequest(new Runnable() { @@ -213,15 +207,15 @@ public class SingleInspectionProfilePanel extends JPanel { InspectionConfigTreeNode node = (InspectionConfigTreeNode)selectionPath.getLastPathComponent(); final Descriptor descriptor = node.getDesriptor(); if (descriptor != null) { - final boolean properSetting = mySelectedProfile.isProperSetting(descriptor.getKey()); - if (node.isProperSetting != properSetting) { + final boolean properSetting = mySelectedProfile.isProperSetting(descriptor.getKey().toString()); + if (node.isProperSetting() != properSetting) { myAlarm.cancelAllRequests(); myAlarm.addRequest(new Runnable() { public void run() { myTree.repaint(); } }, 300); - node.isProperSetting = properSetting; + node.dropCache(); updateUpHierarchy(node, (InspectionConfigTreeNode)node.getParent()); } } @@ -344,7 +338,7 @@ public class SingleInspectionProfilePanel extends JPanel { } @Override public void update(AnActionEvent e) { - e.getPresentation().setEnabled(myRoot.isProperSetting); + e.getPresentation().setEnabled(myRoot.isProperSetting()); } @Override @@ -611,7 +605,7 @@ public class SingleInspectionProfilePanel extends JPanel { mySelectedProfile.disableTool(toolShortName); } } - toolNode.isProperSetting = mySelectedProfile.isProperSetting(key); + toolNode.dropCache(); updateUpHierarchy(toolNode, (InspectionConfigTreeNode)toolNode.getParent()); } final TreePath path = new TreePath(toolNode.getPath()); @@ -622,7 +616,7 @@ public class SingleInspectionProfilePanel extends JPanel { private static void updateUpHierarchy(final InspectionConfigTreeNode node, final InspectionConfigTreeNode parent) { if (parent != null) { - parent.isProperSetting = node.isProperSetting || wasModified(parent); + parent.dropCache(); updateUpHierarchy(parent, (InspectionConfigTreeNode)parent.getParent()); } } @@ -630,7 +624,7 @@ public class SingleInspectionProfilePanel extends JPanel { private static boolean wasModified(InspectionConfigTreeNode node) { for (int i = 0; i < node.getChildCount(); i++) { final InspectionConfigTreeNode childNode = (InspectionConfigTreeNode)node.getChildAt(i); - if (childNode.isProperSetting) { + if (childNode.isProperSetting()) { return true; } } @@ -684,7 +678,7 @@ public class SingleInspectionProfilePanel extends JPanel { if (mySelectedProfile == null) return; myRoot.removeAllChildren(); myRoot.setChecked(false); - myRoot.isProperSetting = false; + myRoot.dropCache(); List> keySetList = new ArrayList>(); final Set quated = new HashSet(); if (filter != null && filter.length() > 0) { @@ -697,18 +691,17 @@ public class SingleInspectionProfilePanel extends JPanel { final List nonDefaultTools = mySelectedProfile.getNonDefaultTools(descriptor.getKey().toString()); final HighlightDisplayKey key = descriptor.getKey(); final boolean enabled = mySelectedProfile.isToolEnabled(key); - final boolean properSetting = mySelectedProfile.isProperSetting(key); boolean hasNonDefaultScope = nonDefaultTools != null && !nonDefaultTools.isEmpty(); - final InspectionConfigTreeNode node = new InspectionConfigTreeNode(descriptor, null, !hasNonDefaultScope, enabled, properSetting, !hasNonDefaultScope); - getGroupNode(myRoot, descriptor.getGroup(), properSetting).add(node); + final InspectionConfigTreeNode node = new InspectionConfigTreeNode(descriptor, null, !hasNonDefaultScope, enabled, !hasNonDefaultScope); + getGroupNode(myRoot, descriptor.getGroup()).add(node); if (hasNonDefaultScope) { for (ScopeToolState nonDefaultState : nonDefaultTools) { - node.add(new InspectionConfigTreeNode(new Descriptor(nonDefaultState, mySelectedProfile), nonDefaultState, false, properSetting, false)); + node.add(new InspectionConfigTreeNode(new Descriptor(nonDefaultState, mySelectedProfile), nonDefaultState, false, false)); } - node.add(new InspectionConfigTreeNode(descriptor, descriptor.getState(), true, properSetting, false)); + node.add(new InspectionConfigTreeNode(descriptor, descriptor.getState(), true, false)); } myRoot.setEnabled(myRoot.isEnabled() || enabled); - myRoot.isProperSetting |= properSetting; + myRoot.dropCache(); } if (filter != null && forceInclude && myRoot.getChildCount() == 0) { final Set filters = SearchableOptionsRegistrar.getInstance().getProcessedWords(filter); @@ -764,7 +757,7 @@ public class SingleInspectionProfilePanel extends JPanel { public void actionPerformed(ActionEvent e) { boolean toUpdate = mySelectedProfile.getErrorLevel(key, scope) != chooser.getLevel(); mySelectedProfile.setErrorLevel(key, chooser.getLevel(), node.isInspectionNode() || node.isByDefault() ? -1 : node.getParent().getIndex(node)); - if (toUpdate) node.isProperSetting = mySelectedProfile.isProperSetting(key); + if (toUpdate) node.dropCache(); } }); chooser.setLevel(mySelectedProfile.getErrorLevel(key, scope)); @@ -805,24 +798,23 @@ public class SingleInspectionProfilePanel extends JPanel { myOptionsPanel.repaint(); } - private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath, boolean properSetting) { + private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath) { InspectionConfigTreeNode currentRoot = root; for (final String group : groupPath) { - currentRoot = getGroupNode(currentRoot, group, properSetting); + currentRoot = getGroupNode(currentRoot, group); } return currentRoot; } - private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String group, boolean properSetting) { + private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String group) { final int childCount = root.getChildCount(); for (int i = 0; i < childCount; i++) { InspectionConfigTreeNode child = (InspectionConfigTreeNode)root.getChildAt(i); if (group.equals(child.getUserObject())) { - child.isProperSetting |= properSetting; return child; } } - InspectionConfigTreeNode child = new InspectionConfigTreeNode(group, null, false, properSetting, false); + InspectionConfigTreeNode child = new InspectionConfigTreeNode(group, null, false, false); root.add(child); return child; } @@ -1070,7 +1062,7 @@ public class SingleInspectionProfilePanel extends JPanel { private void updateErrorLevelUpInHierarchy(HighlightDisplayLevel level, boolean showOptionsAndDescriptorPanels, InspectionConfigTreeNode node) { - node.isProperSetting = false; + node.dropCache(); for (int j = 0; j < node.getChildCount(); j++) { final InspectionConfigTreeNode child = (InspectionConfigTreeNode)node.getChildAt(j); final Object userObject = child.getUserObject(); @@ -1080,7 +1072,6 @@ public class SingleInspectionProfilePanel extends JPanel { else { updateErrorLevelUpInHierarchy(level, showOptionsAndDescriptorPanels, child); } - node.isProperSetting |= child.isProperSetting; } } @@ -1088,7 +1079,7 @@ public class SingleInspectionProfilePanel extends JPanel { final boolean showOptionsAndDescriptorPanels, final HighlightDisplayLevel level) { final HighlightDisplayKey key = child.getDesriptor().getKey(); mySelectedProfile.setErrorLevel(key, level, child.isInspectionNode() || child.isByDefault() ? -1 : child.getParent().getIndex(child)); - child.isProperSetting = mySelectedProfile.isProperSetting(key); + child.dropCache(); if (showOptionsAndDescriptorPanels) { updateOptionsAndDescriptionPanel(new TreePath(child.getPath())); } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java index 67c9e658c90b..1a01b1e19629 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java @@ -20,7 +20,6 @@ */ package com.intellij.profile.codeInspection.ui.actions; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.ex.Descriptor; import com.intellij.codeInspection.ex.InspectionProfileImpl; @@ -97,9 +96,9 @@ public abstract class AddScopeAction extends AnAction { if (node.getChildCount() == 0) { node.add(new InspectionConfigTreeNode(descriptor, getSelectedProfile().getToolDefaultState(descriptor.getKey().getID()), true, true, false)); } - node.insert(new InspectionConfigTreeNode(addedDescriptor, scopeToolState, false, true, false), 0); + node.insert(new InspectionConfigTreeNode(addedDescriptor, scopeToolState, false, false), 0); node.setInspectionNode(false); - node.isProperSetting = getSelectedProfile().isProperSetting(HighlightDisplayKey.find(tool.getShortName())); + node.dropCache(); ((DefaultTreeModel)myTree.getModel()).reload(node); myTree.expandPath(new TreePath(node.getPath())); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java index d00bba8e12d7..a7c4277861f2 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.file.impl; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; @@ -25,6 +26,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.ResolveScopeManager; import com.intellij.psi.impl.source.resolve.FileContextUtil; +import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.util.containers.ConcurrentFactoryMap; @@ -91,6 +93,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { List modulesLibraryUsedIn = new ArrayList(); List orderEntries = projectFileIndex.getOrderEntriesForFile(vFile); + LibraryOrderEntry lib = null; for (OrderEntry entry : orderEntries) { ProgressManager.checkCanceled(); @@ -98,12 +101,32 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { return ((ProjectRootManagerEx)myProjectRootManager).getScopeForJdk((JdkOrderEntry)entry); } - if (entry instanceof LibraryOrderEntry || entry instanceof ModuleOrderEntry) { + if (entry instanceof LibraryOrderEntry) { + lib = (LibraryOrderEntry)entry; + modulesLibraryUsedIn.add(entry.getOwnerModule()); + } + else if (entry instanceof ModuleOrderEntry) { modulesLibraryUsedIn.add(entry.getOwnerModule()); } } - return ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn); + GlobalSearchScope allCandidates = ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn); + if (lib != null) { + final LibraryRuntimeClasspathScope preferred = new LibraryRuntimeClasspathScope(myProject, lib); + // prefer current library + return new DelegatingGlobalSearchScope(allCandidates, preferred) { + @Override + public int compare(VirtualFile file1, VirtualFile file2) { + boolean c1 = preferred.contains(file1); + boolean c2 = preferred.contains(file2); + if (c1 && !c2) return 1; + if (c2 && !c1) return -1; + + return super.compare(file1, file2); + } + }; + } + return allCandidates; } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 84129b3b623a..93b19edb27b4 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -162,7 +162,9 @@ public class InjectedLanguageUtil { @NotNull public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, final PsiFile injectedFile) { if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed()) return hostEditor; - Document document = PsiDocumentManager.getInstance(hostEditor.getProject()).getDocument(injectedFile); + Project project = hostEditor.getProject(); + if (project == null) project = injectedFile.getProject(); + Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile); if (!(document instanceof DocumentWindowImpl)) return hostEditor; DocumentWindowImpl documentWindow = (DocumentWindowImpl)document; SelectionModel selectionModel = hostEditor.getSelectionModel(); diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 3edcb908e65f..2af57b6d6bb2 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -198,7 +198,8 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe @NotNull final Project project, @Nullable final GlobalSearchScope scope, @NotNull final Processor processor) { - FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, scope); + final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance(); + fileBasedIndex.ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, scope); final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); final PsiManager psiManager = PsiManager.getInstance(project); @@ -212,7 +213,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe index.getReadLock().lock(); final ValueContainer container = index.getData(key); - final FileBasedIndex.ProjectIndexableFilesFilter projectFilesFilter = FileBasedIndex.getInstance().projectIndexableFiles(project); + final FileBasedIndex.ProjectIndexableFilesFilter projectFilesFilter = fileBasedIndex.projectIndexableFiles(project); return container.forEach(new ValueContainer.ContainerAction() { @Override @@ -278,7 +279,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - FileBasedIndex.getInstance().requestReindex(file); + fileBasedIndex.requestReindex(file); } }, ModalityState.NON_MODAL); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java b/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java index b8b69cea51eb..ab7c5ef996e4 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java @@ -108,11 +108,14 @@ public class TextOccurrencesUtil { @NotNull String stringToSearch, @NotNull final Collection results, @NotNull final UsageInfoFactory factory) { + final Object lock = new Object(); processUsagesInStringsAndComments(element, stringToSearch, false, new PairProcessor() { public boolean process(PsiElement commentOrLiteral, TextRange textRange) { UsageInfo usageInfo = factory.createUsageInfo(commentOrLiteral, textRange.getStartOffset(), textRange.getEndOffset()); if (usageInfo != null) { - results.add(usageInfo); + synchronized (lock) { + results.add(usageInfo); + } } return true; } diff --git a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java index f753d2500923..cb39f5fd76f6 100644 --- a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java +++ b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java @@ -27,9 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.script.ScriptException; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -103,12 +101,15 @@ public class ExecUtil { } @Nullable - public static String execAndReadLine(@NotNull final List command) { + public static String execAndReadLine(final String... command) { try { - final ProcessOutput output = execAndGetOutput(command, null); - final List lines = output.getStdoutLines(); - if (lines.size() > 0) { - return lines.get(0); + final Process process = new GeneralCommandLine(command).createProcess(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + try { + return reader.readLine(); + } + finally { + reader.close(); } } catch (Exception ignored) { } diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 05f3d11df639..efca09d692a7 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -133,7 +133,7 @@ public class BrowserUtil { if (SystemInfo.isMac || SystemInfo.isWindows) { return true; } - else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen) { + else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { return true; } else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { @@ -152,7 +152,7 @@ public class BrowserUtil { else if (SystemInfo.isMac) { return new String[]{ExecUtil.getOpenCommandPath()}; } - else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen) { + else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { return new String[]{"xdg-open"}; } diff --git a/platform/platform-api/src/com/intellij/ide/UiActivity.java b/platform/platform-api/src/com/intellij/ide/UiActivity.java index baf0d0ce9105..9066837fb0a8 100644 --- a/platform/platform-api/src/com/intellij/ide/UiActivity.java +++ b/platform/platform-api/src/com/intellij/ide/UiActivity.java @@ -17,6 +17,7 @@ package com.intellij.ide; import com.intellij.util.ui.update.ComparableObject; import com.intellij.util.ui.update.ComparableObjectCheck; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -38,6 +39,7 @@ public class UiActivity implements ComparableObject{ } } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myElements}; diff --git a/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java b/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java index 0f9a05a55653..146be9277bce 100644 --- a/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java +++ b/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java @@ -247,6 +247,7 @@ public class PresentationData implements ColoredItemPresentation, ComparableObje mySeparatorAbove = false; } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myOpenIcon, myClosedIcon, myColoredText, myAttributesKey, myFont, myForcedTextForeground, myPresentableText, myLocationString, mySeparatorAbove}; diff --git a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java index f4175389bee6..705df1ef8530 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java @@ -26,8 +26,11 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.PlatformUtils; +import com.intellij.util.SystemProperties; +import com.intellij.util.ui.UIUtil; import com.intellij.util.xmlb.Accessor; import com.intellij.util.xmlb.SerializationFilter; import com.intellij.util.xmlb.XmlSerializerUtil; @@ -107,19 +110,15 @@ public class UISettings implements PersistentStateComponent, Exporta */ public static final int TABS_NONE = 0; - /** - * Invoked by reflection. - */ public UISettings() { - tweakPlatformDefaults(); myListenerList = new EventListenerList(); + tweakPlatformDefaults(); setSystemFontFaceAndSize(); } private void tweakPlatformDefaults() { // TODO: Make it pluggable if (PlatformUtils.isCidr()) { - //HIDE_TOOL_STRIPES = true; SHOW_MAIN_TOOLBAR = false; SHOW_ICONS_IN_MENUS = false; SHOW_MEMORY_INDICATOR = false; @@ -133,7 +132,7 @@ public class UISettings implements PersistentStateComponent, Exporta myListenerList.add(UISettingsListener.class, listener); } - public void addUISettingsListener(@NotNull final UISettingsListener listener, @NotNull Disposable parentDisposable){ + public void addUISettingsListener(@NotNull final UISettingsListener listener, @NotNull Disposable parentDisposable) { myListenerList.add(UISettingsListener.class,listener); Disposer.register(parentDisposable, new Disposable() { @Override @@ -146,7 +145,7 @@ public class UISettings implements PersistentStateComponent, Exporta /** * Notifies all registered listeners that UI settings has been changed. */ - public void fireUISettingsChanged(){ + public void fireUISettingsChanged() { UISettingsListener[] listeners= myListenerList.getListeners(UISettingsListener.class); for (UISettingsListener listener : listeners) { listener.uiSettingsChanged(this); @@ -166,29 +165,18 @@ public class UISettings implements PersistentStateComponent, Exporta return application != null ? getInstance() : new UISettings(); } - public void removeUISettingsListener(UISettingsListener listener){ + public void removeUISettingsListener(UISettingsListener listener) { myListenerList.remove(UISettingsListener.class,listener); } - private void setDefaultFontSettings() { - final Application application = ApplicationManager.getApplication(); - if (application == null) { - // we're the shadow settings - return; - } - FONT_FACE = SystemInfo.isLinux && application.isUnitTestMode() ? "Dialog.plain" : "Dialog"; - FONT_SIZE = 12; - } - - private static boolean isValidFont(final Font font){ + private static boolean isValidFont(final Font font) { try { - return - font.canDisplay('a') && - font.canDisplay('z') && - font.canDisplay('A') && - font.canDisplay('Z') && - font.canDisplay('0') && - font.canDisplay('1'); + return font.canDisplay('a') && + font.canDisplay('z') && + font.canDisplay('A') && + font.canDisplay('Z') && + font.canDisplay('0') && + font.canDisplay('1'); } catch (Exception e) { // JRE has problems working with the font. Just skip. @@ -196,30 +184,41 @@ public class UISettings implements PersistentStateComponent, Exporta } } - /** - * Under Win32 it's possible to determine face and size of default fount. - */ - private void setSystemFontFaceAndSize(){ - if(FONT_FACE == null || FONT_SIZE <= 0){ - if(SystemInfo.isWindows){ - //noinspection HardCodedStringLiteral - Font font=(Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font"); - if(font != null){ - FONT_FACE = font.getName(); - FONT_SIZE = font.getSize(); - }else{ - setDefaultFontSettings(); - } - }else{ // UNIXes go here - setDefaultFontSettings(); + private void setSystemFontFaceAndSize() { + if (FONT_FACE == null || FONT_SIZE <= 0) { + final Pair fontData = getSystemFontFaceAndSize(); + FONT_FACE = fontData.first; + FONT_SIZE = fontData.second; + } + } + + private static Pair getSystemFontFaceAndSize() { + final Pair fontData = UIUtil.getSystemFontData(); + if (fontData != null) { + return fontData; + } + + if (SystemInfo.isWindows) { + //noinspection HardCodedStringLiteral + final Font font = (Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font"); + if (font != null) { + return Pair.create(font.getName(), font.getSize()); } } + + return Pair.create("Dialog", 12); + } + + public static class FontFilter implements SerializationFilter { + public boolean accepts(Accessor accessor, Object bean) { + UISettings settings = (UISettings)bean; + return !hasDefaultFontSetting(settings); + } } private static boolean hasDefaultFontSetting(final UISettings settings) { - Font font=(Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font"); - return SystemInfo.isWindows && font != null && settings.FONT_FACE.equals(font.getName()) && settings.FONT_SIZE == font.getSize(); - + final Pair fontData = getSystemFontFaceAndSize(); + return fontData.first.equals(settings.FONT_FACE) && fontData.second.equals(settings.FONT_SIZE); } public UISettings getState() { @@ -230,28 +229,27 @@ public class UISettings implements PersistentStateComponent, Exporta XmlSerializerUtil.copyBean(object, this); // Check tab placement in editor - if( - EDITOR_TAB_PLACEMENT != TABS_NONE && - EDITOR_TAB_PLACEMENT != SwingConstants.TOP&& - EDITOR_TAB_PLACEMENT != SwingConstants.LEFT&& - EDITOR_TAB_PLACEMENT != SwingConstants.BOTTOM&& - EDITOR_TAB_PLACEMENT != SwingConstants.RIGHT - ){ - EDITOR_TAB_PLACEMENT=SwingConstants.TOP; + if (EDITOR_TAB_PLACEMENT != TABS_NONE && + EDITOR_TAB_PLACEMENT != SwingConstants.TOP && + EDITOR_TAB_PLACEMENT != SwingConstants.LEFT && + EDITOR_TAB_PLACEMENT != SwingConstants.BOTTOM && + EDITOR_TAB_PLACEMENT != SwingConstants.RIGHT) { + EDITOR_TAB_PLACEMENT = SwingConstants.TOP; } - // Check that alpha ration in in valid range - if(ALPHA_MODE_DELAY<0){ - ALPHA_MODE_DELAY=1500; + + // Check that alpha delay and ratio are valid + if (ALPHA_MODE_DELAY < 0) { + ALPHA_MODE_DELAY = 1500; } - if(ALPHA_MODE_RATIO< 0.0f ||ALPHA_MODE_RATIO>1.0f){ - ALPHA_MODE_RATIO=0.5f; + if (ALPHA_MODE_RATIO < 0.0f || ALPHA_MODE_RATIO > 1.0f) { + ALPHA_MODE_RATIO = 0.5f; } setSystemFontFaceAndSize(); - // 1. Sometimes system font cannot display standard ASCI symbols. If so we have + // 1. Sometimes system font cannot display standard ASCII symbols. If so we have // find any other suitable font withing "preferred" fonts first. boolean fontIsValid = isValidFont(new Font(FONT_FACE, Font.PLAIN, FONT_SIZE)); - if(!fontIsValid){ + if (!fontIsValid) { @NonNls final String[] preferredFonts = {"dialog", "Arial", "Tahoma"}; for (String preferredFont : preferredFonts) { if (isValidFont(new Font(preferredFont, Font.PLAIN, FONT_SIZE))) { @@ -263,7 +261,7 @@ public class UISettings implements PersistentStateComponent, Exporta // 2. If all preferred fonts are not valid in current environment // we have to find first valid font (if any) - if(!fontIsValid){ + if (!fontIsValid) { Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for (Font font : fonts) { if (isValidFont(font)) { @@ -278,23 +276,13 @@ public class UISettings implements PersistentStateComponent, Exporta MAX_CLIPBOARD_CONTENTS = 5; } - fireUISettingsChanged(); } - public static class FontFilter implements SerializationFilter { - public boolean accepts(Accessor accessor, Object bean) { - UISettings settings = (UISettings)bean; - - return !hasDefaultFontSetting(settings); - } - - } - - private static final boolean DONT_TOUCH_ALIASING = "true".equalsIgnoreCase(System.getProperty("idea.use.default.antialiasing.in.editor")); + private static final boolean DEFAULT_ALIASING = SystemProperties.getBooleanProperty("idea.use.default.antialiasing.in.editor", false); public static void setupAntialiasing(final Graphics g) { - if (DONT_TOUCH_ALIASING) return; + if (DEFAULT_ALIASING) return; Graphics2D g2d=(Graphics2D)g; UISettings uiSettings=getInstance(); @@ -350,10 +338,8 @@ public class UISettings implements PersistentStateComponent, Exporta } public void initComponent() { - } public void disposeComponent() { - } } diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java index f7d793af382d..fb1f1d8ab1b5 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java @@ -24,13 +24,15 @@ import org.jetbrains.annotations.NotNull; */ public class ExtensionFileNameMatcher implements FileNameMatcher { private final String myExtension; - + private final String myDotExtension; + public ExtensionFileNameMatcher(@NotNull @NonNls String extension) { myExtension = extension.toLowerCase(); + myDotExtension = "." + myExtension; } public boolean accept(@NotNull @NonNls String fileName) { - return fileName.regionMatches(true, fileName.length() - myExtension.length() - 1, "." + myExtension, 0, myExtension.length() + 1); + return fileName.regionMatches(true, fileName.length() - myDotExtension.length(), myDotExtension, 0, myDotExtension.length()); } @NonNls diff --git a/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java b/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java index df59623806dd..d18d087232c2 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java +++ b/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java @@ -16,17 +16,18 @@ package com.intellij.openapi.util; import com.intellij.util.ui.update.ComparableObject; +import org.jetbrains.annotations.NotNull; public abstract class ActiveRunnable extends ComparableObject.Impl { protected ActiveRunnable() { } - protected ActiveRunnable(final Object object) { + protected ActiveRunnable(@NotNull Object object) { super(object); } - protected ActiveRunnable(final Object[] objects) { + protected ActiveRunnable(@NotNull Object[] objects) { super(objects); } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java b/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java index 53c8c5b651be..21ddd3bd36c4 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java @@ -16,7 +16,10 @@ package com.intellij.openapi.vfs; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -26,6 +29,24 @@ public abstract class ReadonlyStatusHandler { return !getInstance(project).ensureFilesWritable(files).hasReadonlyFiles(); } + public static boolean ensureDocumentWritable(@NotNull Project project, @NotNull Document document) { + final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + boolean okWritable; + if (psiFile != null) { + final VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile != null) { + okWritable = ensureFilesWritable(project, virtualFile); + } + else { + okWritable = psiFile.isWritable(); + } + } + else { + okWritable = document.isWritable(); + } + return okWritable; + } + public abstract static class OperationStatus { @NotNull public abstract VirtualFile[] getReadonlyFiles(); diff --git a/platform/platform-api/src/com/intellij/ui/GuiUtils.java b/platform/platform-api/src/com/intellij/ui/GuiUtils.java index 6abc627f752f..68c970d04780 100644 --- a/platform/platform-api/src/com/intellij/ui/GuiUtils.java +++ b/platform/platform-api/src/com/intellij/ui/GuiUtils.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; @@ -382,4 +383,18 @@ public class GuiUtils { invokeAndWait(runnable); } } + + /** + * Runs the runnable, if called from the dispatch thread. + * Otherwise calls {@link Application#invokeAndWait(Runnable, com.intellij.openapi.application.ModalityState)} + */ + public static void invokeAndWaitIfNeeded(@NotNull Runnable runnable, @NotNull ModalityState modalityState) { + Application application = ApplicationManager.getApplication(); + if (application.isDispatchThread()) { + runnable.run(); + } + else { + application.invokeAndWait(runnable, modalityState); + } + } } diff --git a/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java b/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java index 4d5cf2d20b6b..f1f86b754ab1 100644 --- a/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java +++ b/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java @@ -1,6 +1,7 @@ package com.intellij.ui.border; import com.intellij.ui.TitledSeparator; +import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -20,19 +21,25 @@ public class IdeaTitledBorder extends TitledBorder { super(title); titledSeparator = new TitledSeparator(title); titledSeparator.setText(title); + DialogUtil.registerMnemonic(titledSeparator.getLabel(), null); this.outsideInsets = new Insets(insets.top, insets.left, insets.bottom, insets.right); this.insideInsets = new Insets(TitledSeparator.BOTTOM_INSET, indent, 0, 0); } + @Override + public void setTitle(String title) { + super.setTitle(title); + titledSeparator.setText(title); + } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { int labelX = x + outsideInsets.left; int labelY = y + outsideInsets.top; TitledSeparator titledSeparator = getTitledSeparator(c); - titledSeparator.setText(title); JLabel label = titledSeparator.getLabel(); Dimension labelSize = label.getPreferredSize(); label.setSize(labelSize); diff --git a/platform/platform-api/src/com/intellij/ui/navigation/Place.java b/platform/platform-api/src/com/intellij/ui/navigation/Place.java index cc88c74b6745..1bddf5a01215 100644 --- a/platform/platform-api/src/com/intellij/ui/navigation/Place.java +++ b/platform/platform-api/src/com/intellij/ui/navigation/Place.java @@ -29,6 +29,7 @@ public class Place implements ComparableObject { private LinkedHashMap myPath = new LinkedHashMap(); + @NotNull public final Object[] getEqualityObjects() { return new Object[] {myPath}; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 53ec6dcc98ab..4ec35a3fd404 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -3221,6 +3221,7 @@ public class JBTabsImpl extends JComponent return myInfo.getText(); } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myInfo}; diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java index f39d2581d301..780680254082 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.FileStatus; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.update.ComparableObject; import com.intellij.util.ui.update.ComparableObjectCheck; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -263,6 +264,7 @@ public abstract class SimpleNode extends PresentableNodeDescriptor implements Co return list.toArray(new ColoredFragment[list.size()]); } + @NotNull public Object[] getEqualityObjects() { return NONE; } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java index 9b391992054f..b8b944ff8a46 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java @@ -243,6 +243,7 @@ public class FilteringTreeStructure extends AbstractTreeStructure { return super.getWeight(); } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myDelegate}; } diff --git a/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java b/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java index 27f0ac706660..6a04e529ffaa 100644 --- a/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java @@ -16,6 +16,7 @@ package com.intellij.util.ui; import com.intellij.ide.ui.UISettings; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -66,7 +67,7 @@ public class DialogUtil{ } } - public static void registerMnemonic(JLabel label, JComponent target) { + public static void registerMnemonic(JLabel label, @Nullable JComponent target) { registerMnemonic(label, target, UIUtil.MNEMONIC); } @@ -76,7 +77,7 @@ public class DialogUtil{ * @param mn mnemonic char * @since 11.0 */ - public static void registerMnemonic(JLabel label, JComponent target, char mn) { + public static void registerMnemonic(JLabel label, @Nullable JComponent target, char mn) { String text = label.getText(); if (text != null) { final StringBuilder realText = new StringBuilder(text.length()); diff --git a/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java b/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java index 059da22b5e34..f4f815b77116 100644 --- a/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java +++ b/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java @@ -73,8 +73,9 @@ public class RangeBlinker { MarkupModel markupModel = myEditor.getMarkupModel(); if (show) { - for (Segment rangeMarker : myMarkers) { - RangeHighlighter highlighter = markupModel.addRangeHighlighter(rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), + for (Segment segment : myMarkers) { + if (segment.getEndOffset() > myEditor.getDocument().getTextLength()) continue; + RangeHighlighter highlighter = markupModel.addRangeHighlighter(segment.getStartOffset(), segment.getEndOffset(), HighlighterLayer.ADDITIONAL_SYNTAX, myAttributes, HighlighterTargetArea.EXACT_RANGE); myAddedHighlighters.add(highlighter); @@ -85,6 +86,7 @@ public class RangeBlinker { } stopBlinking(); myBlinkingAlarm.addRequest(new Runnable() { + @Override public void run() { if (myTimeToLive > 0 || show) { myTimeToLive--; diff --git a/platform/platform-api/src/com/intellij/util/ui/RefreshFileSystemIcon.java b/platform/platform-api/src/com/intellij/util/ui/RefreshFileSystemIcon.java new file mode 100644 index 000000000000..dea652841547 --- /dev/null +++ b/platform/platform-api/src/com/intellij/util/ui/RefreshFileSystemIcon.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.ui; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class RefreshFileSystemIcon extends AnimatedIcon { + private static final Icon[] ICONS = getIcons("/process/fs/step_", 18); + + private static Icon[] getIcons(String path, int count) { + Icon[] icons = new Icon[count]; + for (int i = 0; i < icons.length; i++) { + int index = i + 1; + icons[i] = IconLoader.getIcon(path + index + ".png"); + } + return icons; + } + + public RefreshFileSystemIcon() { + super("Refreshing filesystem", ICONS, EmptyIcon.ICON_16, 800); + } + + @Override + public Dimension getPreferredSize() { + if (!isRunning()) return new Dimension(0, 0); + return super.getPreferredSize(); + } + + @Override + public void paint(Graphics g) { + g.translate(0, -1); + super.paint(g); + g.translate(0, 1); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java b/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java index 59511366ce00..44224ed6f10e 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java @@ -50,7 +50,7 @@ public class IdeTooltip extends ComparableObject.Impl { private Ui myUi; - private boolean hint = false; + private boolean myHint = false; public IdeTooltip(Component component, Point point, JComponent tipComponent, Object... identity) { @@ -235,12 +235,12 @@ public class IdeTooltip extends ComparableObject.Impl { } public IdeTooltip setHint(boolean hint) { - this.hint = hint; + this.myHint = hint; return this; } public boolean isHint() { - return hint; + return myHint; } public boolean isInside(RelativePoint target) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java index cbfaa06466b8..aa929d43c63b 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java @@ -41,7 +41,7 @@ public class RevealFileAction extends DumbAwareAction { @NotNull public static String getActionName() { - return SystemInfo.isMac ? "Reveal in Finder" : "Show in " + SystemInfo.nativeFileManagerName; + return SystemInfo.isMac ? "Reveal in Finder" : "Show in " + SystemInfo.getFileManagerName(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java index c7a065c40589..7d29e02c02a6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java @@ -35,6 +35,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.JarFileSystem; @@ -51,11 +52,19 @@ import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; public class ShowFilePathAction extends AnAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.ShowFilePathAction"); + private static NotNullLazyValue hasNautilusV3 = new NotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + final String version = ExecUtil.execAndReadLine("nautilus", "--version"); + return version != null && version.startsWith("GNOME nautilus 3"); + } + }; + @Override public void update(final AnActionEvent e) { if (SystemInfo.isMac || !isSupported()) { @@ -166,7 +175,7 @@ public class ShowFilePathAction extends AnAction { public static boolean isSupported() { return SystemInfo.isWindows || Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN) || - SystemInfo.hasXdgOpen || SystemInfo.hasNautilus; + SystemInfo.hasXdgOpen() || SystemInfo.hasNautilus(); } /** @deprecated use {@linkplain #openFile(java.io.File)} (to remove in IDEA 13) */ @@ -231,7 +240,7 @@ public class ShowFilePathAction extends AnAction { return; } - if (Registry.is("ide.use.nautilus3") && SystemInfo.hasNautilus && hasNautilusV3()) { + if (Registry.is("ide.use.nautilus3") && SystemInfo.hasNautilus() && hasNautilusV3.getValue()) { if (toSelect != null) { new GeneralCommandLine("nautilus", toSelect.getCanonicalPath()).createProcess(); } @@ -242,10 +251,10 @@ public class ShowFilePathAction extends AnAction { } final String path = dir.getCanonicalPath(); - if (SystemInfo.hasXdgOpen) { + if (SystemInfo.hasXdgOpen()) { new GeneralCommandLine("/usr/bin/xdg-open", path).createProcess(); } - else if (SystemInfo.hasNautilus) { + else if (SystemInfo.hasNautilus()) { new GeneralCommandLine("nautilus", path).createProcess(); } else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) { @@ -256,16 +265,6 @@ public class ShowFilePathAction extends AnAction { } } - private static Boolean hasNautilusV3 = null; - - private static boolean hasNautilusV3() { - if (hasNautilusV3 == null) { - final String version = ExecUtil.execAndReadLine(Arrays.asList("nautilus", "--version")); - hasNautilusV3 = version != null && version.startsWith("GNOME nautilus 3"); - } - return hasNautilusV3; - } - @Nullable private static VirtualFile getFile(final AnActionEvent e) { return PlatformDataKeys.VIRTUAL_FILE.getData(e.getDataContext()); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java index 1c99f828dcf8..ed5914b49483 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java @@ -44,6 +44,6 @@ public class ShowLogAction extends AnAction implements DumbAware { @NotNull public static String getActionName() { - return "Reveal Log in " + SystemInfo.nativeFileManagerName; + return "Reveal Log in " + SystemInfo.getFileManagerName(); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 63b0ae1525a1..697399225e26 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,8 +32,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; @@ -43,10 +45,8 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.openapi.wm.impl.ToolWindowManagerImpl; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.Gray; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.SimpleTextAttributes; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; +import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; @@ -62,6 +62,8 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.util.*; import java.util.List; @@ -74,6 +76,8 @@ import static java.awt.event.KeyEvent.*; @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod", "SSBasedInspection"}) public class Switcher extends AnAction implements DumbAware { private static volatile SwitcherPanel SWITCHER = null; + private static final Icon PIN_ON = IconLoader.getIcon("/general/autohideOn.png"); + private static final Icon PIN_OFF = IconLoader.getIcon("/general/autohideOff.png"); private static final Color BORDER_COLOR = Gray._135; private static final Color SEPARATOR_COLOR = BORDER_COLOR.brighter(); @NonNls private static final String SWITCHER_FEATURE_ID = "switcher"; @@ -121,10 +125,12 @@ public class Switcher extends AnAction implements DumbAware { ToolWindow tw; if (SWITCHER != null && event instanceof KeyEvent) { final KeyEvent keyEvent = (KeyEvent)event; - if (event.getID() == KEY_RELEASED && keyEvent.getKeyCode() == CTRL_KEY && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if (event.getID() == KEY_RELEASED && keyEvent.getKeyCode() == CTRL_KEY && isAutoHide()) { SwingUtilities.invokeLater(CHECKER); } - else if (event.getID() == KEY_PRESSED && (tw = SWITCHER.twShortcuts.get(String.valueOf((char)keyEvent.getKeyCode()))) != null) { + else if (isAutoHide() + && event.getID() == KEY_PRESSED + && (tw = SWITCHER.twShortcuts.get(String.valueOf((char)keyEvent.getKeyCode()))) != null) { SWITCHER.myPopup.closeOk(null); tw.activate(null, true, true); } @@ -176,6 +182,7 @@ public class Switcher extends AnAction implements DumbAware { final Project project; final Map twShortcuts; final Alarm myAlarm; + final SwitcherSpeedSearch mySpeedSearch = isAutoHide() ? null : new SwitcherSpeedSearch(); @SuppressWarnings({"ManualArrayToCollectionCopy"}) SwitcherPanel(Project project) { @@ -185,7 +192,7 @@ public class Switcher extends AnAction implements DumbAware { addKeyListener(this); setBorder(new EmptyBorder(0, 0, 0, 0)); setBackground(Color.WHITE); - pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); + pathLabel.setHorizontalAlignment(SwingConstants.LEFT); final Font font = pathLabel.getFont(); pathLabel.setFont(font.deriveFont((float)10)); @@ -200,7 +207,19 @@ public class Switcher extends AnAction implements DumbAware { }; descriptions.setBorder(BorderFactory.createEmptyBorder(1, 4, 1, 4)); - descriptions.add(pathLabel); + descriptions.add(pathLabel, BorderLayout.CENTER); + final JLabel pinLabel = new JLabel(isPinnedMode() ? PIN_ON : PIN_OFF); + pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode"); + pinLabel.setBorder(IdeBorderFactory.createEmptyBorder(0, 10, 0, 0)); + descriptions.add(pinLabel, BorderLayout.EAST); + pinLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE = !UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; + pinLabel.setIcon(isPinnedMode() ? PIN_ON : PIN_OFF); + pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode"); + } + }); twManager = ToolWindowManager.getInstance(project); final DefaultListModel twModel = new DefaultListModel(); for (String id : twManager.getToolWindowIds()) { @@ -225,7 +244,7 @@ public class Switcher extends AnAction implements DumbAware { toolWindows = new JBList(twModel); toolWindows.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); toolWindows.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - toolWindows.setCellRenderer(new SwitcherToolWindowsListRenderer(ids, map) { + toolWindows.setCellRenderer(new SwitcherToolWindowsListRenderer(mySpeedSearch, ids, map) { @Override public Component getListCellRendererComponent(JList list, Object value, @@ -274,11 +293,32 @@ public class Switcher extends AnAction implements DumbAware { for (Pair pair : editorManager.getSelectionHistory()) { editors.add(new FileInfo(pair.first, pair.second)); } - if (editors.size() < 2) { + if (editors.size() < 2 || isPinnedMode()) { + if (isPinnedMode() && editors.size() > 1) { + filesData.addAll(editors); + } final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles()); - final int len = Math.min(toolWindows.getModel().getSize(), Math.max(editors.size(), recentFiles.length)); + final int maxFiles = Math.max(editors.size(), recentFiles.length); + final int len = isPinnedMode() ? maxFiles : Math.min(toolWindows.getModel().getSize(), maxFiles); + boolean firstRecentMarked = false; for (int i = 0; i < len; i++) { - filesData.add(new FileInfo(recentFiles[i], null)); + final FileInfo info = new FileInfo(recentFiles[i], null); + boolean add = true; + if (isPinnedMode()) { + for (FileInfo fileInfo : filesData) { + if (fileInfo.first.equals(info.first)) { + add = false; + break; + } + } + } + if (add) { + filesData.add(info); + if (!firstRecentMarked) { + firstRecentMarked = true; + info.isSeparator = true; + } + } } if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) { filesData.add(0, editors.get(0)); @@ -297,7 +337,7 @@ public class Switcher extends AnAction implements DumbAware { files = new JBList(filesModel); files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); files.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); - files.setCellRenderer(new VirtualFilesRenderer(project) { + files.setCellRenderer(new VirtualFilesRenderer(project, mySpeedSearch) { @Override public Component getListCellRendererComponent(JList list, Object value, @@ -381,19 +421,33 @@ public class Switcher extends AnAction implements DumbAware { .setRequestFocus(true) .setTitle(SWITCHER_TITLE) .setMovable(false) + .setCancelKeyEnabled(false) .setCancelCallback(new Computable() { - public Boolean compute() { - SWITCHER = null; - return true; - } - }).createPopup(); + public Boolean compute() { + SWITCHER = null; + return true; + } + }).createPopup(); - new AnAction(null, null, null){ + if (isPinnedMode()) { + new AnAction(null, null, null) { @Override public void actionPerformed(AnActionEvent e) { //suppress all actions to activate a toolwindow : IDEA-71277 } }.registerCustomShortcutSet(TW_SHORTCUT, this, myPopup); + new AnAction(null, null, null) { + + @Override + public void actionPerformed(AnActionEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { + mySpeedSearch.hidePopup(); + } else { + myPopup.cancel(); + } + } + }.registerCustomShortcutSet(CustomShortcutSet.fromString("ESCAPE"), this, myPopup); + } Component comp = null; final EditorWindow result = FileEditorManagerEx.getInstanceEx(project).getActiveWindow().getResult(); @@ -407,6 +461,7 @@ public class Switcher extends AnAction implements DumbAware { myPopup.showInCenterOf(comp); } + private Map createShortcuts(List windows) { final Map keymap = new HashMap(windows.size()); final List pluginToolWindows = new ArrayList(); @@ -441,7 +496,7 @@ public class Switcher extends AnAction implements DumbAware { } public void keyReleased(KeyEvent e) { - if ((e.getKeyCode() == CTRL_KEY && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) + if ((e.getKeyCode() == CTRL_KEY && isAutoHide()) || e.getKeyCode() == VK_ENTER) { navigate(); } else @@ -453,6 +508,8 @@ public class Switcher extends AnAction implements DumbAware { } public void keyPressed(KeyEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) return; + switch (e.getKeyCode()) { case VK_UP: goBack(); @@ -546,7 +603,7 @@ public class Switcher extends AnAction implements DumbAware { } private void goRight() { - if ((isFilesSelected() || !isFilesVisible()) && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if ((isFilesSelected() || !isFilesVisible()) && isAutoHide()) { cancel(); } else { @@ -562,7 +619,7 @@ public class Switcher extends AnAction implements DumbAware { } private void goLeft() { - if (isToolWindowsSelected() && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if (isToolWindowsSelected() && isAutoHide()) { cancel(); } else { @@ -699,29 +756,117 @@ public class Switcher extends AnAction implements DumbAware { repaintLists(); } public void mouseDragged(MouseEvent e) {} + + private class SwitcherSpeedSearch extends SpeedSearchBase implements PropertyChangeListener { + private Object[] myElements; + + public SwitcherSpeedSearch() { + super(SwitcherPanel.this); + addChangeListener(this); + setComparator(new SpeedSearchComparator(false, true)); + } + + @Override + protected int getSelectedIndex() { + return isFilesSelected() + ? files.getSelectedIndex() + : files.getModel().getSize() + toolWindows.getSelectedIndex(); + } + + @Override + protected Object[] getAllElements() { + if (myElements == null) { + final SwitcherPanel switcher = SwitcherPanel.this; + final Object[] files = ((DefaultListModel)switcher.files.getModel()).toArray(); + final Object[] toolWindows = ((DefaultListModel)switcher.toolWindows.getModel()).toArray(); + myElements = new Object[files.length + toolWindows.length]; + System.arraycopy(files, 0, myElements, 0, files.length); + System.arraycopy(toolWindows, 0, myElements, files.length, toolWindows.length); + } + return myElements; + } + + + @Override + protected String getElementText(Object element) { + return element instanceof ToolWindow + ? ids.get(element) + : element instanceof FileInfo + ? ((FileInfo)element).getFirst().getName() : ""; + } + + @Override + protected void selectElement(Object element, String selectedText) { + if (element instanceof FileInfo) { + toolWindows.getSelectionModel().clearSelection(); + files.setSelectedValue(element, false); + } else { + files.clearSelection(); + toolWindows.setSelectedValue(element, false); + } + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + files.repaint(); + toolWindows.repaint(); + } + } + } + + private static boolean isAutoHide() { + return UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; + } + + private static boolean isPinnedMode() { + return !isAutoHide(); } private static class VirtualFilesRenderer extends ColoredListCellRenderer { private final Project myProject; + private final SpeedSearchBase mySearch; + private boolean hide = false; + private boolean separator = false; - public VirtualFilesRenderer(Project project) { + public VirtualFilesRenderer(Project project, SpeedSearchBase search) { myProject = project; + mySearch = search; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + hide = false; if (value instanceof FileInfo) { final VirtualFile virtualFile = ((FileInfo)value).first; final String name = virtualFile.getPresentableName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); + separator = ((FileInfo)value).isSeparator; + + if ( mySearch != null && mySearch.isPopupActive()) { + hide = mySearch.matchingFragments(name) == null && !StringUtil.isEmpty(mySearch.getEnteredPrefix()); + } final FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile); final TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); } } + + @Override + protected void doPaint(Graphics2D g) { + GraphicsConfig config = new GraphicsConfig(g); + if (hide) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); + } + super.doPaint(g); + config.restore(); + if (separator) { + UIUtil.drawDottedLine(g, 0, 0, getWidth(), 0, Color.WHITE, Color.BLACK); + } + } } private static class FileInfo extends Pair { + boolean isSeparator = false; public FileInfo(VirtualFile first, EditorWindow second) { super(first, second); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java b/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java index c56a31fd792d..e9117d735aa7 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,15 @@ */ package com.intellij.ide.actions; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.SpeedSearchBase; import com.intellij.util.PlatformIcons; import javax.swing.*; @@ -34,26 +38,51 @@ import java.util.Map; class SwitcherToolWindowsListRenderer extends ColoredListCellRenderer { private static final Map iconCache = new HashMap(); private static final SimpleTextAttributes ID_STYLE = new SimpleTextAttributes(SimpleTextAttributes.STYLE_UNDERLINE, Color.black); + private final SpeedSearchBase mySpeedSearch; private final Map ids; private final Map shortcuts; + private boolean hide = false; - SwitcherToolWindowsListRenderer(Map ids, Map shortcuts) { + SwitcherToolWindowsListRenderer(SpeedSearchBase speedSearch, + Map ids, + Map shortcuts) { + mySpeedSearch = speedSearch; this.ids = ids; this.shortcuts = shortcuts; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + hide = false; if (value instanceof ToolWindow) { final ToolWindow tw = (ToolWindow)value; setIcon(getIcon(tw)); - append(shortcuts.get(tw), ID_STYLE); - final String name = ": " + ids.get(tw); + final String name; + + if (UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + append(shortcuts.get(tw), ID_STYLE); + name = ": " + ids.get(tw); + } else { + name = ids.get(tw); + } final TextAttributes attributes = new TextAttributes(Color.BLACK, null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { + hide = mySpeedSearch.matchingFragments(ids.get(tw)) == null && !StringUtil.isEmpty(mySpeedSearch.getEnteredPrefix()); + } } } + @Override + protected void doPaint(Graphics2D g) { + GraphicsConfig config = new GraphicsConfig(g); + if (hide) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); + } + super.doPaint(g); + config.restore(); + } + private Icon getIcon(ToolWindow toolWindow) { Icon icon = iconCache.get(ids.get(toolWindow)); if (icon != null) return icon; diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java index 82fad28a4996..c632778b2646 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java @@ -26,6 +26,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.GuiUtils; import java.io.UnsupportedEncodingException; import java.util.HashMap; @@ -182,7 +183,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } if (key.get() == null) { final Ref ex = new Ref(); - ApplicationManager.getApplication().invokeAndWait(new Runnable() { + GuiUtils.invokeAndWaitIfNeeded(new Runnable() { public void run() { if (key.get() == null) { try { diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java index 21254efc1ba6..798875c744f9 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java @@ -18,12 +18,12 @@ package com.intellij.ide.passwordSafe.ui; import com.intellij.ide.passwordSafe.PasswordSafe; import com.intellij.ide.passwordSafe.PasswordSafeException; import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; +import com.intellij.ui.GuiUtils; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -273,7 +273,7 @@ public class PasswordSafePromptDialog extends DialogWrapper { } } final AtomicReference pw = new AtomicReference(null); - ApplicationManager.getApplication().invokeAndWait(new Runnable() { + GuiUtils.invokeAndWaitIfNeeded(new Runnable() { public void run() { final PasswordSafePromptDialog d = new PasswordSafePromptDialog(project, ps, title, message); if (promptLabel != null) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java index 67cbb85de98b..2b29ce9e87ab 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java @@ -661,19 +661,19 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo defaults.put("Tree.ancestorInputMap", null); int uiFontSize = myUiSettings.FONT_SIZE; String uiFontFace = myUiSettings.FONT_FACE; - FontUIResource font = new FontUIResource(uiFontFace, Font.PLAIN, uiFontSize); - FontUIResource font1 = new FontUIResource("Serif", Font.PLAIN, uiFontSize); - FontUIResource font3 = new FontUIResource("Monospaced", Font.PLAIN, uiFontSize); + FontUIResource uiFont = new FontUIResource(uiFontFace, Font.PLAIN, uiFontSize); + FontUIResource textFont = new FontUIResource("Serif", Font.PLAIN, uiFontSize); + FontUIResource monoFont = new FontUIResource("Monospaced", Font.PLAIN, uiFontSize); for (String fontResource : ourPatchableFontResources) { - defaults.put(fontResource, font); + defaults.put(fontResource, uiFont); } - defaults.put("PasswordField.font", font3); - defaults.put("TextArea.font", font3); - defaults.put("TextPane.font", font1); - defaults.put("EditorPane.font", font1); - defaults.put("TitledBorder.font", font); + defaults.put("PasswordField.font", monoFont); + defaults.put("TextArea.font", monoFont); + defaults.put("TextPane.font", textFont); + defaults.put("EditorPane.font", textFont); + defaults.put("TitledBorder.font", uiFont); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index ec3cb318914c..fa0f805fa22d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -73,6 +73,8 @@ import org.picocontainer.MutablePicoContainer; import javax.swing.*; import java.awt.*; +import java.io.BufferedInputStream; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java index faca9fb447ed..553b31a4e6f2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java @@ -40,13 +40,13 @@ import java.util.Comparator; public abstract class Change { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.Change"); - private void apply(FragmentSide original) { + private void apply(@NotNull FragmentSide original) { FragmentSide targetSide = original.otherSide(); RangeMarker originalRangeMarker = getRangeMarker(original); RangeMarker rangeMarker = getRangeMarker(targetSide); if (originalRangeMarker != null && rangeMarker != null) { - ChangeType.apply(originalRangeMarker, rangeMarker); + ChangeType.apply(getProject(), originalRangeMarker, rangeMarker); if (isValid()) { removeFromList(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java index e444ae67651e..fceefcf3cdf3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java @@ -25,7 +25,9 @@ import com.intellij.openapi.editor.markup.HighlighterLayer; import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.SeparatorPlacement; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -92,8 +94,9 @@ public class ChangeType { return CHANGE; } - public static void apply(RangeMarker original, RangeMarker target) { + public static void apply(@NotNull Project project, @NotNull RangeMarker original, @NotNull RangeMarker target) { Document document = target.getDocument(); + if (!ReadonlyStatusHandler.ensureDocumentWritable(project, document)) return; if (DocumentUtil.isEmpty(original)) { int offset = target.getStartOffset(); document.deleteString(offset, target.getEndOffset()); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java index b1567ece92f1..d15496b1a543 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java @@ -17,6 +17,7 @@ package com.intellij.openapi.diff.impl.util; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; +import org.jetbrains.annotations.NotNull; public class DocumentUtil { @@ -24,7 +25,7 @@ public class DocumentUtil { return range.getDocument().getText().substring(range.getStartOffset(), range.getEndOffset()); } - public static boolean isEmpty(RangeMarker rangeMarker) { + public static boolean isEmpty(@NotNull RangeMarker rangeMarker) { return rangeMarker.getStartOffset() == rangeMarker.getEndOffset(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java index 195fe6ffcd35..9236d90ae977 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java @@ -34,5 +34,6 @@ public interface ErrorStripTooltipRendererProvider { TooltipRenderer calcTooltipRenderer(@NotNull String text); TooltipRenderer calcTooltipRenderer(@NotNull String text, int width); - TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor); + @NotNull + TrafficTooltipRenderer createTrafficTooltipRenderer(@NotNull Runnable onHide, @NotNull Editor editor); } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 9179a8ce4f7d..4e0e3c1d6ff9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -2628,6 +2628,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int myCount = 0; @NotNull final FontInfo myFontType; + final boolean myHasBreakSymbols; final int spaceWidth; @Nullable private char[] myLastData; @@ -2635,6 +2636,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private CachedFontContent(@NotNull FontInfo fontInfo) { myFontType = fontInfo; spaceWidth = fontInfo.charWidth(' ', myEditorComponent); + myHasBreakSymbols = fontInfo.hasGlyphsToBreakDrawingIteration(); } private void flushContent(@NotNull Graphics g) { @@ -2666,7 +2668,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi final int lastCount = count - 1; final Color lastColor = color[lastCount]; if (_data == myLastData && _start == ends[lastCount] && (_color == null || lastColor == null || _color.equals(lastColor)) - && _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */) + && _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */ + && (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data[ends[lastCount] - 1]))) { ends[lastCount] = _end; if (lastColor == null) color[lastCount] = _color; @@ -3054,6 +3057,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myForceRefreshFont = true; } endX += charWidth; + + if (newFont.hasGlyphsToBreakDrawingIteration() && newFont.getSymbolsToBreakDrawingIteration().contains(c)) { + drawCharsCached(g, text, start, j + 1, x, y, fontType, fontColor); + x = endX; + start = j + 1; + } } if (!(x < clip.x && endX < clip.x || x > clip.x + clip.width && endX > clip.x + clip.width)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 698ddff7dabd..2b11e3e28c5a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -813,8 +813,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark return new LineTooltipRenderer(text, width, new Object[] {text}); } + @NotNull @Override - public TrafficTooltipRenderer createTrafficTooltipRenderer(final Runnable onHide, Editor editor) { + public TrafficTooltipRenderer createTrafficTooltipRenderer(@NotNull final Runnable onHide, @NotNull Editor editor) { return new TrafficTooltipRenderer() { @Override public void repaintTooltipWindow() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java index 9aaafa8a07b9..c7f7cbdc8d1c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,21 @@ package com.intellij.openapi.editor.impl; import gnu.trove.TIntHashSet; import org.intellij.lang.annotations.JdkConstants; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.image.BufferedImage; /** * @author max */ public class FontInfo { + + private final TIntHashSet mySymbolsToBreakDrawingIteration = new TIntHashSet(); + private final String myFamilyName; private final Font myFont; private final int mySize; @@ -32,12 +39,63 @@ public class FontInfo { private final TIntHashSet mySafeCharacters = new TIntHashSet(); private FontMetrics myFontMetrics = null; private final int[] charWidth = new int[128]; + private final boolean myHasGlyphsToBreakDrawingIteration; public FontInfo(final String familyName, final int size, @JdkConstants.FontStyle int style) { myFamilyName = familyName; mySize = size; myStyle = style; myFont = new Font(familyName, style, size); + + parseProblemGlyphs(); + myHasGlyphsToBreakDrawingIteration = !mySymbolsToBreakDrawingIteration.isEmpty(); + } + + private void parseProblemGlyphs() { + BufferedImage buffer = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB); + final Graphics graphics = buffer.getGraphics(); + if (!(graphics instanceof Graphics2D)) { + return; + } + final FontRenderContext context = ((Graphics2D)graphics).getFontRenderContext(); + char[] charBuffer = new char[1]; + for (char c = 0; c < 128; c++) { + if (!myFont.canDisplay(c)) { + continue; + } + charBuffer[0] = c; + final GlyphVector vector = myFont.createGlyphVector(context, charBuffer); + final float y = vector.getGlyphMetrics(0).getAdvanceY(); + if (Math.round(y) != 0) { + mySymbolsToBreakDrawingIteration.add(c); + } + } + } + + /** + * We've experienced a problem that particular symbols from particular font are represented really weird + * by the IJ editor (IDEA-83645). + *

+ * Eventually it was found out that outline font glyphs can have a 'y advance', i.e. instruction on how the subsequent + * glyphs location should be adjusted after painting the current glyph. In terms of java that means that such a problem + * glyph should be the last symbol at the {@link Graphics#drawChars(char[], int, int, int, int) text drawing iteration}. + *

+ * Hopefully, such glyphs are exceptions from the normal processing, so, this method allows to answer whether a font + * {@link #getFont() referenced} by the current object has such a glyph. + * + * @return true if the {@link #getFont() target font} has problem glyphs; false otherwise + */ + public boolean hasGlyphsToBreakDrawingIteration() { + return myHasGlyphsToBreakDrawingIteration; + } + + /** + * @return unicode symbols which glyphs {@link #hasGlyphsToBreakDrawingIteration() have problems} + * at the {@link #getFont() target font}. + */ + @NotNull + public TIntHashSet getSymbolsToBreakDrawingIteration() { + return mySymbolsToBreakDrawingIteration; } public boolean canDisplay(char c) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index be81bbc8b2ea..20cc6e469da5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -166,7 +166,7 @@ public class EditorsSplitters extends JPanel { painter.appendLine("Open a file by name with " + getActionShortcutText("GotoFile")).smaller().withBullet() .appendLine("Open Recent files with " + getActionShortcutText("RecentFiles")).smaller().withBullet() .appendLine("Open Navigation Bar with " + getActionShortcutText("ShowNavBar")).smaller().withBullet() - .appendLine("Drag'n'Drop file(s) here from " + SystemInfo.nativeFileManagerName).smaller().withBullet() + .appendLine("Drag'n'Drop file(s) here from " + SystemInfo.getFileManagerName()).smaller().withBullet() .draw(g, new PairFunction>() { @Override public Pair fun(Integer width, Integer height) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java index 460b3ffe3810..a47f9ca87997 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java @@ -556,6 +556,7 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh return myContent.getDisplayName(); } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myContent}; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index 0de178212d6d..7cbd2336fe4d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,10 +41,7 @@ import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; import com.intellij.ui.components.panels.Wrapper; import com.intellij.util.Alarm; -import com.intellij.util.ui.AbstractLayoutManager; -import com.intellij.util.ui.AsyncProcessIcon; -import com.intellij.util.ui.EmptyIcon; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.*; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NotNull; @@ -63,7 +60,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge private final StatusPanel myInfoPanel = new StatusPanel(); private final JPanel myRefreshAndInfoPanel = new JPanel(); - private final AsyncProcessIcon myProgressIcon; + private final AnimatedIcon myProgressIcon; private final ArrayList myOriginals = new ArrayList(); private final ArrayList myInfos = new ArrayList(); @@ -78,7 +75,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge private boolean myShouldClosePopupAndOnProcessFinish; private final Alarm myRefreshAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - private AsyncProcessIcon myRefreshIcon; + private AnimatedIcon myRefreshIcon; private EmptyIcon myEmptyRefreshIcon; private String myCurrentRequestor; @@ -89,24 +86,25 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge setOpaque(false); - myRefreshIcon = new AsyncProcessIcon("Refreshing filesystem") { - protected Icon getPassiveIcon() { - return myEmptyRefreshIcon; - } - - @Override - public Dimension getPreferredSize() { - if (!isRunning()) return new Dimension(0, 0); - return super.getPreferredSize(); - } - - @Override - public void paint(Graphics g) { - g.translate(0, -1); - super.paint(g); - g.translate(0, 1); - } - }; + myRefreshIcon = new RefreshFileSystemIcon(); + // new AsyncProcessIcon("Refreshing filesystem") { + // protected Icon getPassiveIcon() { + // return myEmptyRefreshIcon; + // } + // + // @Override + // public Dimension getPreferredSize() { + // if (!isRunning()) return new Dimension(0, 0); + // return super.getPreferredSize(); + // } + // + // @Override + // public void paint(Graphics g) { + // g.translate(0, -1); + // super.paint(g); + // g.translate(0, 1); + // } + //}; myRefreshIcon.setPaintPassiveIcon(false); myEmptyRefreshIcon = new EmptyIcon(0, myRefreshIcon.getPreferredSize().height); diff --git a/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java b/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java index e6f2553604c3..374c3fa89a0c 100644 --- a/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java @@ -115,17 +115,17 @@ public class HeavyweightHint implements Hint { } @Override - public void setLocation(RelativePoint point) { + public void setLocation(@NotNull RelativePoint point) { if (myWindow != null) { myWindow.setLocation(point.getScreenPoint().x, point.getScreenPoint().y); } } - public void addHintListener(HintListener listener) { + public void addHintListener(@NotNull HintListener listener) { myListenerList.add(HintListener.class, listener); } - public void removeHintListener(HintListener listener) { + public void removeHintListener(@NotNull HintListener listener) { myListenerList.remove(HintListener.class, listener); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/Hint.java b/platform/platform-impl/src/com/intellij/ui/Hint.java index 451ee6fbffd9..bbdba268e32b 100644 --- a/platform/platform-impl/src/com/intellij/ui/Hint.java +++ b/platform/platform-impl/src/com/intellij/ui/Hint.java @@ -48,13 +48,13 @@ public interface Hint { */ void hide(); - void addHintListener(HintListener listener); + void addHintListener(@NotNull HintListener listener); - void removeHintListener(HintListener listener); + void removeHintListener(@NotNull HintListener listener); void pack(); - void setLocation(RelativePoint point); + void setLocation(@NotNull RelativePoint point); /** * Pack and set location diff --git a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java index 0f09b4ec66dc..895b38a61e3e 100644 --- a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java @@ -110,6 +110,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { * are in parentComponent coordinate system. Note that the component * appears on 250 layer. */ + @Override public void show(@NotNull final JComponent parentComponent, final int x, final int y, @@ -129,29 +130,33 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myComponent.validate(); if (!myForceShowAsPopup && - (myForceLightweightPopup || fitsLayeredPane(layeredPane, myComponent, new RelativePoint(parentComponent, new Point(x, y)), hintHint))) { + (myForceLightweightPopup || + fitsLayeredPane(layeredPane, myComponent, new RelativePoint(parentComponent, new Point(x, y)), hintHint))) { beforeShow(); final Dimension preferredSize = myComponent.getPreferredSize(); if (hintHint.isAwtTooltip()) { - IdeTooltip tooltip = new IdeTooltip(hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent, hintHint, myComponent) { - @Override - protected boolean canAutohideOn(TooltipEvent event) { - if (event.getInputEvent() instanceof MouseEvent) { - return !(hintHint.isContentActive() && event.isIsEventInsideBalloon()); - } else if (event.getAction() != null) { - return false; - } else { - return true; + IdeTooltip tooltip = + new IdeTooltip(hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent, hintHint, myComponent) { + @Override + protected boolean canAutohideOn(TooltipEvent event) { + if (event.getInputEvent() instanceof MouseEvent) { + return !(hintHint.isContentActive() && event.isIsEventInsideBalloon()); + } + else if (event.getAction() != null) { + return false; + } + else { + return true; + } } - } - @Override - protected void onHidden() { - fireHintHidden(); - TooltipController.getInstance().resetCurrent(); - } + @Override + protected void onHidden() { + fireHintHidden(); + TooltipController.getInstance().resetCurrent(); + } @Override public boolean canBeDismissedOnTimeout() { @@ -170,7 +175,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { .setHint(true); myComponent.validate(); myCurrentIdeTooltip = IdeTooltipManager.getInstance().show(tooltip, hintHint.isShowImmediately()); - } else { + } + else { final Point layeredPanePoint = SwingUtilities.convertPoint(parentComponent, x, y, layeredPane); myComponent.setBounds(layeredPanePoint.x, layeredPanePoint.y, preferredSize.width, preferredSize.height); layeredPane.add(myComponent, JLayeredPane.POPUP_LAYER); @@ -218,8 +224,9 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myPopup.show(new RelativePoint(myParentComponent, new Point(actualPoint.x, actualPoint.y))); } } - - protected void onPopupCancel() {} + + protected void onPopupCancel() { + } private void fixActualPoint(Point actualPoint) { if (!isAwtTooltip()) return; @@ -263,11 +270,13 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (pos == Balloon.Position.above || pos == Balloon.Position.below) { boolean heightFit = target.y - size.height - pointer > 0 || target.y + size.height + pointer < paneSize.height; return heightFit && size.width + pointer < paneSize.width; - } else { + } + else { boolean widthFit = target.x - size.width - pointer > 0 || target.x + size.width + pointer < paneSize.width; return widthFit && size.height + pointer < paneSize.height; } - } else { + } + else { final Rectangle lpRect = new Rectangle(pane.getLocationOnScreen().x, pane.getLocationOnScreen().y, pane.getWidth(), pane.getHeight()); Rectangle componentRect = new Rectangle(desiredLocation.getScreenPoint().x, desiredLocation.getScreenPoint().y, @@ -291,12 +300,15 @@ public class LightweightHint extends UserDataHolderBase implements Hint { return myComponent.getBounds(); } + @Override public boolean isVisible() { if (myIsRealPopup) { return myPopup != null && myPopup.isVisible(); - } else if (myCurrentIdeTooltip != null) { + } + else if (myCurrentIdeTooltip != null) { return myComponent.isShowing() || IdeTooltipManager.getInstance().isQueuedToShow(myCurrentIdeTooltip); - } else { + } + else { return myComponent.isShowing(); } } @@ -305,6 +317,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { return myIsRealPopup | myForceShowAsPopup; } + @Override public void hide() { hide(false); } @@ -314,7 +327,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (myIsRealPopup) { if (ok) { myPopup.closeOk(null); - } else { + } + else { myPopup.cancel(); } myPopup = null; @@ -324,7 +338,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { IdeTooltip tooltip = myCurrentIdeTooltip; myCurrentIdeTooltip = null; tooltip.hide(); - } else { + } + else { final JRootPane rootPane = myComponent.getRootPane(); if (rootPane != null) { final Rectangle bounds = myComponent.getBounds(); @@ -375,11 +390,13 @@ public class LightweightHint extends UserDataHolderBase implements Hint { return myComponent; } - public final void addHintListener(final HintListener listener) { + @Override + public final void addHintListener(@NotNull final HintListener listener) { myListenerList.add(HintListener.class, listener); } - public final void removeHintListener(final HintListener listener) { + @Override + public final void removeHintListener(@NotNull final HintListener listener) { myListenerList.remove(HintListener.class, listener); } @@ -388,13 +405,14 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (isRealPopup()) { location = myPopup.getLocationOnScreen(); SwingUtilities.convertPointFromScreen(location, c); - } else { + } + else { if (myCurrentIdeTooltip != null) { Point tipPoint = myCurrentIdeTooltip.getPoint(); Component tipComponent = myCurrentIdeTooltip.getComponent(); return SwingUtilities.convertPoint(tipComponent, tipPoint, c); - - } else { + } + else { location = SwingUtilities.convertPoint( myComponent.getParent(), myComponent.getLocation(), @@ -407,10 +425,11 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } @Override - public void setLocation(RelativePoint point) { + public void setLocation(@NotNull RelativePoint point) { if (isRealPopup()) { myPopup.setLocation(point.getScreenPoint()); - } else { + } + else { if (myCurrentIdeTooltip != null) { Point screenPoint = point.getScreenPoint(); if (!screenPoint.equals(new RelativePoint(myCurrentIdeTooltip.getComponent(), myCurrentIdeTooltip.getPoint()).getScreenPoint())) { @@ -418,7 +437,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myCurrentIdeTooltip.setComponent(point.getComponent()); IdeTooltipManager.getInstance().show(myCurrentIdeTooltip, true, false); } - } else { + } + else { Point targetPoint = point.getPoint(myComponent.getParent()); myComponent.setLocation(targetPoint); @@ -431,11 +451,13 @@ public class LightweightHint extends UserDataHolderBase implements Hint { public void setSize(Dimension size) { if (myIsRealPopup) { myPopup.setSize(size); - } else { + } + else { //todo kirillk if (isAwtTooltip()) { return; - } else { + } + else { myComponent.setSize(size); myComponent.revalidate(); @@ -458,14 +480,17 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (myIsRealPopup) { Window wnd = SwingUtilities.getWindowAncestor(myComponent); return wnd.getBounds().contains(target.getScreenPoint()); - } else if (myCurrentIdeTooltip != null) { + } + else if (myCurrentIdeTooltip != null) { return myCurrentIdeTooltip.isInside(target); - } else { + } + else { return new Rectangle(myComponent.getLocationOnScreen(), myComponent.getSize()).contains(target.getScreenPoint()); } } private final class MyEscListener implements ActionListener { + @Override public final void actionPerformed(final ActionEvent e) { hide(); } @@ -477,7 +502,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } public boolean canControlAutoHide() { - return myCurrentIdeTooltip != null && myCurrentIdeTooltip.getTipComponent().isShowing() ; + return myCurrentIdeTooltip != null && myCurrentIdeTooltip.getTipComponent().isShowing(); } public IdeTooltip getCurrentIdeTooltip() { diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java index 797edb0b4f98..458426a846dd 100644 --- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java +++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.DataManager; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; @@ -198,6 +199,15 @@ public abstract class SpeedSearchBase extends SpeedSear final Object element = it.next(); if (isMatchingElement(element, _s)) return element; } + + if (UISettings.getInstance().CYCLE_SCROLLING) { + final ListIterator i = getElementIterator(0); + while (i.hasNext()) { + final Object element = i.next(); + if (isMatchingElement(element, _s)) return element; + } + } + return ( current != null && isMatchingElement(current, _s) ) ? current : null; } @@ -217,6 +227,15 @@ public abstract class SpeedSearchBase extends SpeedSear final Object element = it.previous(); if (isMatchingElement(element, _s)) return element; } + + if (UISettings.getInstance().CYCLE_SCROLLING) { + final ListIterator i = getElementIterator(getAllElements().length); + while (i.hasPrevious()) { + final Object element = i.previous(); + if (isMatchingElement(element, _s)) return element; + } + } + return selectedIndex != -1 && isMatchingElement(current, _s) ? current : null; } diff --git a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java index 81be185a1aa4..eae298f2cd06 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java @@ -19,7 +19,12 @@ import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.testFramework.LeakHunter; +import com.intellij.testFramework.TestFileType; +import org.jetbrains.annotations.NonNls; import java.io.IOException; import java.util.ArrayList; @@ -30,7 +35,6 @@ import java.util.List; * @since 12/27/10 1:43 PM */ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModificationTest { - private final List myBookmarks = new ArrayList(); @Override @@ -43,13 +47,13 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif } public void testWholeTextReplace() throws IOException { - String text = + @NonNls String text = "public class Test {\n" + " public void test() {\n" + " int i = 1;\n" + " }\n" + "}"; - init(text); + init(text, TestFileType.TEXT); addBookmark(2); List bookmarksBefore = getManager().getValidBookmarks(); @@ -60,19 +64,19 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif assertEquals(1, bookmarksAfter.size()); assertSame(bookmarksBefore.get(0), bookmarksAfter.get(0)); for (Bookmark bookmark : bookmarksAfter) { - checkBookmark(bookmark); + checkBookmarkNavigation(bookmark); } } public void testBookmarkLineRemove() throws IOException { - String text = + @NonNls String text = "public class Test {\n" + " public void test() {\n" + " int i = 1;\n" + " }\n" + "}"; - init(text); - + init(text, TestFileType.TEXT); + addBookmark(2); Document document = myEditor.getDocument(); myEditor.getSelectionModel().setSelection(document.getLineStartOffset(2) - 1, document.getLineEndOffset(2)); @@ -81,13 +85,13 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif } public void testBookmarkIsSavedAfterRemoteChange() throws IOException { - String text = + @NonNls String text = "public class Test {\n" + " public void test() {\n" + " int i = 1;\n" + " }\n" + "}"; - init(text); + init(text, TestFileType.TEXT); addBookmark(2); myEditor.getDocument().setText("111\n222" + text + "333"); @@ -95,7 +99,29 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif assertEquals(1, bookmarks.size()); Bookmark bookmark = bookmarks.get(0); assertEquals(3, bookmark.getLine()); - checkBookmark(bookmark); + checkBookmarkNavigation(bookmark); + } + + public void testBookmarkManagerDoesNotHardReferenceDocuments() throws IOException { + @NonNls String text = + "public class Test {\n" + + "}"; + + myVFile = getSourceRoot().createChildData(null, getTestName(false) + ".txt"); + VfsUtil.saveText(myVFile, text); + + Bookmark bookmark = getManager().addTextBookmark(myVFile, 1, "xxx"); + assertNotNull(bookmark); + LeakHunter.checkLeak(getManager(), Document.class); + + Document document = FileDocumentManager.getInstance().getDocument(myVFile); + assertNotNull(document); + + document.insertString(0, "line 0\n"); + assertEquals(2, bookmark.getLine()); + + myEditor = createEditor(myVFile); + checkBookmarkNavigation(bookmark); } private void addBookmark(int line) { @@ -106,8 +132,16 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif private static BookmarkManager getManager() { return BookmarkManager.getInstance(getProject()); } - - private static void checkBookmark(Bookmark bookmark) { + + @Override + public Object getData(String dataId) { + if (dataId.equals(OpenFileDescriptor.NAVIGATE_IN_EDITOR.getName())) { + return myEditor; + } + return super.getData(dataId); + } + + private static void checkBookmarkNavigation(Bookmark bookmark) { int line = bookmark.getLine(); int anotherLine = line; if (line > 0) { @@ -118,9 +152,7 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif } CaretModel caretModel = myEditor.getCaretModel(); caretModel.moveToLogicalPosition(new LogicalPosition(anotherLine, 0)); - OpenFileDescriptor target = bookmark.getTarget(); - assertTrue(target.canNavigate()); - target.navigateIn(myEditor); + bookmark.navigate(); assertEquals(line, caretModel.getLogicalPosition().line); } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java index d9a2fc1ccfb2..daeed2381f55 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java @@ -44,12 +44,7 @@ import java.util.regex.Pattern; * @since 11/18/10 7:43 PM */ public abstract class AbstractEditorProcessingOnDocumentModificationTest extends LightPlatformCodeInsightTestCase { - - protected void init(String fileText) throws IOException { - init(fileText, TestFileType.TEXT); - } - - protected void init(String fileText, TestFileType type) throws IOException { + protected void init(@NotNull String fileText, @NotNull TestFileType type) throws IOException { configureFromFileText(getFileName(type), fileText); } diff --git a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java index 480dc6312069..4f66a034eae0 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java @@ -30,10 +30,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; @@ -278,4 +275,26 @@ import java.util.Collection; } }.execute().throwException(); } + + public static void addLibrary(final Module module, + final String libName, final String libDir, + final String[] classRoots, + final String[] sourceRoots) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); + final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, libDir); + final Library library = model.getModuleLibraryTable().createLibrary(libName); + final Library.ModifiableModel libModifiableModel = library.getModifiableModel(); + for (String classRoot : classRoots) { + libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES); + } + for (String sourceRoot : sourceRoots) { + libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES); + } + libModifiableModel.commit(); + model.commit(); + } + }); + } } \ No newline at end of file diff --git a/platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java b/platform/util-rt/src/com/intellij/openapi/diagnostic/LoggerRt.java similarity index 89% rename from platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java rename to platform/util-rt/src/com/intellij/openapi/diagnostic/LoggerRt.java index 8eb116e18585..2e25291e4b6c 100644 --- a/platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java +++ b/platform/util-rt/src/com/intellij/openapi/diagnostic/LoggerRt.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.diagnostic.rt; +package com.intellij.openapi.diagnostic; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -22,15 +22,16 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Method; import java.util.logging.Level; import java.util.logging.LogManager; +import java.util.logging.Logger; /** * A wrapper which uses either IDE logging subsystem (if available) or java.util.logging. * * @since 12.0 */ -public abstract class Logger { +public abstract class LoggerRt { private interface Factory { - Logger getInstance(@NotNull @NonNls final String category); + LoggerRt getInstance(@NotNull @NonNls final String category); } private static Factory ourFactory; @@ -48,7 +49,7 @@ public abstract class Logger { } @NotNull - public static Logger getInstance(@NotNull @NonNls final String category) { + public static LoggerRt getInstance(@NotNull @NonNls final String category) { return getFactory().getInstance(category); } @@ -84,9 +85,9 @@ public abstract class Logger { private final LogManager myManager = LogManager.getLogManager(); @Override - public Logger getInstance(@NotNull @NonNls final String category) { - final java.util.logging.Logger logger = myManager.getLogger(category); - return new Logger() { + public LoggerRt getInstance(@NotNull @NonNls final String category) { + final Logger logger = myManager.getLogger(category); + return new LoggerRt() { @Override public void info(@Nullable @NonNls final String message, @Nullable final Throwable t) { logger.log(Level.INFO, message, t); @@ -124,10 +125,10 @@ public abstract class Logger { } @Override - public Logger getInstance(@NotNull @NonNls final String category) { + public LoggerRt getInstance(@NotNull @NonNls final String category) { try { final Object logger = myGetInstance.invoke(null, category); - return new Logger() { + return new LoggerRt() { @Override public void info(@Nullable @NonNls final String message, @Nullable final Throwable t) { try { diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index 2881afe12457..1b7440f97c56 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.util.io; -import com.intellij.openapi.diagnostic.rt.Logger; +import com.intellij.openapi.diagnostic.LoggerRt; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.text.StringUtilRt; import org.jetbrains.annotations.NonNls; @@ -34,7 +34,7 @@ import java.util.UUID; */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class FileUtilRt { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtilLight"); + private static final LoggerRt LOG = LoggerRt.getInstance("#com.intellij.openapi.util.io.FileUtilLight"); protected static final ThreadLocal BUFFER = new ThreadLocal() { protected byte[] initialValue() { diff --git a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java index 9c9390371f87..ea51d5f5ddc0 100644 --- a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java +++ b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java @@ -35,4 +35,8 @@ public abstract class NotNullLazyValue { } return myValue; } + + public void drop() { + myValue = null; + } } \ No newline at end of file diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index c62c32b6a71e..5921da2f0e62 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -51,9 +51,6 @@ public class SystemInfo extends SystemInfoRt { public static final boolean isKDE = _SUN_DESKTOP.contains("kde"); public static final boolean isGnome = _SUN_DESKTOP.contains("gnome"); - public static final boolean hasNautilus = isUnix && new File("/usr/bin/nautilus").canExecute(); - public static final boolean hasXdgOpen = isUnix && new File("/usr/bin/xdg-open").canExecute(); - public static final boolean isMacSystemMenu = isMac && "true".equals(System.getProperty("apple.laf.useScreenMenuBar")); public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive; @@ -65,10 +62,46 @@ public class SystemInfo extends SystemInfoRt { public static final boolean isAMD64 = "amd64".equals(OS_ARCH); public static final boolean isMacIntel64 = isMac && "x86_64".equals(OS_ARCH); - public static final String nativeFileManagerName = isMac ? "Finder" : - isWindows ? "Explorer" : - hasNautilus ? "Nautilus" : - "File Manager"; + /** @deprecated use {@linkplain #hasXdgOpen()} (to remove in IDEA 13) */ + public static final boolean hasXdgOpen = false; + private static final NotNullLazyValue ourHasXdgOpen = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + return isUnix && new File("/usr/bin/xdg-open").canExecute(); + } + }; + public static boolean hasXdgOpen() { + return ourHasXdgOpen.getValue(); + } + + private static final NotNullLazyValue hasNautilus = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + return isUnix && new File("/usr/bin/nautilus").canExecute(); + } + }; + public static boolean hasNautilus() { + return hasNautilus.getValue(); + } + + /** @deprecated use {@linkplain #getFileManagerName()} (to remove in IDEA 13) */ + public static final String nativeFileManagerName = "File Manager"; + private static final NotNullLazyValue ourFileManagerName = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected String compute() { + return isMac ? "Finder" : + isWindows ? "Explorer" : + hasNautilus() ? "Nautilus" : + "File Manager"; + } + }; + @NotNull + public static String getFileManagerName() { + return ourFileManagerName.getValue(); + } /** * Whether IDEA is running under MacOS X version 10.4 or later. diff --git a/platform/util/src/com/intellij/util/SystemProperties.java b/platform/util/src/com/intellij/util/SystemProperties.java index 6f7750c5d982..6a0bbdfa5e8c 100644 --- a/platform/util/src/com/intellij/util/SystemProperties.java +++ b/platform/util/src/com/intellij/util/SystemProperties.java @@ -110,4 +110,21 @@ public class SystemProperties { return defaultValue; } + + /** + * Returns the value of given property as a boolean. + * Returns {@code defaultValue} if property is not specified or malformed. + * + * @param key the property name + * @param defaultValue default value + * @return the property value as integer, or default value. + */ + public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) { + final String value = System.getProperty(key); + if (value != null) { + return Boolean.parseBoolean(value); + } + + return defaultValue; + } } diff --git a/platform/util/src/com/intellij/util/WalkingState.java b/platform/util/src/com/intellij/util/WalkingState.java index 9106b72fa6d2..c4bcb1db6081 100644 --- a/platform/util/src/com/intellij/util/WalkingState.java +++ b/platform/util/src/com/intellij/util/WalkingState.java @@ -48,8 +48,12 @@ public class WalkingState { if (!startedWalking) { stopped = false; startedWalking = true; - walkChildren(element); - startedWalking = false; + try { + walkChildren(element); + } + finally { + startedWalking = false; + } } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 002432d18d20..ce17aba15305 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -70,7 +70,6 @@ import java.util.regex.Pattern; */ @SuppressWarnings("StaticMethodOnlyUsedInOneClass") public class UIUtil { - private static final String TABLE_DECORATION_KEY = "TABLE_DECORATION_KEY"; private static final Color DECORATED_ROW_BG_COLOR = new Color(242, 245, 249); @@ -136,6 +135,8 @@ public class UIUtil { // accessed only from EDT private static final HashMap ourAppleDotSamples = new HashMap(); + private static volatile Pair ourSystemFontData = null; + @NonNls private static final String ROOT_PANE = "JRootPane.future"; private UIUtil() { } @@ -1745,18 +1746,23 @@ public class UIUtil { } } - /** @deprecated use {@linkplain #initDefaultLAF()} (to remove in IDEA 12) */ - public static void initDefaultLAF(final String productName) { - initDefaultLAF(); - } - public static void initDefaultLAF() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + + if (ourSystemFontData == null) { + final Font font = getLabelFont(); + ourSystemFontData = Pair.create(font.getName(), font.getSize()); + } } catch (Exception ignored) { } } + @Nullable + public static Pair getSystemFontData() { + return ourSystemFontData; + } + public static void addKeyboardShortcut(final JComponent target, final AbstractButton button, final KeyStroke keyStroke) { target.registerKeyboardAction( new ActionListener() { diff --git a/platform/util/src/com/intellij/util/ui/update/ComparableObject.java b/platform/util/src/com/intellij/util/ui/update/ComparableObject.java index bfe5f48d776e..dea34bd8b0f9 100644 --- a/platform/util/src/com/intellij/util/ui/update/ComparableObject.java +++ b/platform/util/src/com/intellij/util/ui/update/ComparableObject.java @@ -16,40 +16,43 @@ package com.intellij.util.ui.update; import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; public interface ComparableObject { - Object[] NONE = ArrayUtil.EMPTY_OBJECT_ARRAY; + @NotNull Object[] getEqualityObjects(); class Impl implements ComparableObject { - - private Object[] myObjects; + private final Object[] myObjects; public Impl() { this(NONE); } - public Impl(Object object) { + public Impl(@NotNull Object object) { this(new Object[] {object}); } - public Impl(Object[] objects) { + public Impl(@NotNull Object[] objects) { myObjects = objects; } + @NotNull + @Override public Object[] getEqualityObjects() { return myObjects; } + @Override public final boolean equals(Object obj) { return ComparableObjectCheck.equals(this, obj); } + @Override public final int hashCode() { return ComparableObjectCheck.hashCode(this, super.hashCode()); } } - } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java index 42b5a2838876..82bd8486d1ec 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,36 +18,35 @@ package com.intellij.openapi.vcs.changes.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.patch.BinaryFilePatch; import com.intellij.openapi.diff.impl.patch.FilePatch; import com.intellij.openapi.diff.impl.patch.IdeaTextPatchBuilder; import com.intellij.openapi.diff.impl.patch.formove.PatchApplier; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.BackgroundFromStartOption; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeList; -import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.ui.ChangeListChooser; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.WaitForProgressToShow; import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; abstract class RevertCommittedStuffAbstractAction extends AnAction implements DumbAware { private final Convertor myForUpdateConvertor; private final Convertor myForPerformConvertor; + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.actions.RevertCommittedStuffAbstractAction"); public RevertCommittedStuffAbstractAction(final Convertor forUpdateConvertor, final Convertor forPerformConvertor) { @@ -63,6 +62,7 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du if (changes == null || changes.length == 0) return; final List changesList = new ArrayList(); Collections.addAll(changesList, changes); + FileDocumentManager.getInstance().saveAllDocuments(); String defaultName = null; final ChangeList[] changeLists = e.getData(VcsDataKeys.CHANGE_LISTS); @@ -81,7 +81,8 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du @Override public void run(@NotNull ProgressIndicator indicator) { try { - patches.addAll(IdeaTextPatchBuilder.buildPatch(project, changesList, baseDir.getPresentableUrl(), true)); + final List preprocessed = preprocessChanges(changesList); + patches.addAll(IdeaTextPatchBuilder.buildPatch(project, preprocessed, baseDir.getPresentableUrl(), true)); } catch (final VcsException ex) { WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { @@ -101,6 +102,35 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du }); } + private List preprocessChanges(List list) { + final List result = new ArrayList(); + final Map map = new HashMap(); + for (Change change : list) { + if (change.getBeforeRevision() == null) { + result.add(change); + } else { + final FilePath beforePath = ChangesUtil.getBeforePath(change); + final Change existing = map.get(beforePath); + if (existing == null) { + map.put(beforePath, change); + continue; + } + if (change.getAfterRevision() == null && existing.getAfterRevision() == null) continue; + if (change.getAfterRevision() != null && existing.getAfterRevision() != null) { + LOG.error("Incorrect changes list: " + list); + } + if (existing.getAfterRevision() != null && change.getAfterRevision() == null) { + continue; // skip delete change + } + if (change.getAfterRevision() != null && existing.getAfterRevision() == null) { + map.put(beforePath, change); // skip delete change + } + } + } + result.addAll(map.values()); + return result; + } + public void update(final AnActionEvent e) { final Project project = e.getData(PlatformDataKeys.PROJECT); final Change[] changes = myForUpdateConvertor.convert(e); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java index 2b1b63bf1b6f..70428d9c5989 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,7 +95,8 @@ public class VcsGeneralConfigurationPanel implements SearchableConfigurable { } myPromptsPanel.setSize(myPromptsPanel.getPreferredSize()); - myOnPatchCreation.setName((SystemInfo.isMac ? "Reveal patch in" : "Show patch in ") + SystemInfo.nativeFileManagerName + " after creation:"); + myOnPatchCreation.setName((SystemInfo.isMac ? "Reveal patch in" : "Show patch in ") + + SystemInfo.getFileManagerName() + " after creation:"); } public void apply() throws ConfigurationException { diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java index c22c7b18bf16..f5d7ae50e4df 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java @@ -38,7 +38,6 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.xml.XmlFile; @@ -50,7 +49,6 @@ import org.jetbrains.android.uipreview.LocaleData; import org.jetbrains.android.uipreview.RenderUtil; import org.jetbrains.android.uipreview.RenderingException; import org.jetbrains.android.util.AndroidSdkNotConfiguredException; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -67,6 +65,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { private final ExternalPSIChangeListener myPSIChangeListener; private final ProfileAction myProfileAction; private volatile RenderSession mySession; + private boolean myParseTime; public AndroidDesignerEditorPanel(@NotNull Module module, @NotNull VirtualFile file) { super(module, file); @@ -169,26 +168,22 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { } private void reparseFile() { - try { - myToolProvider.loadDefaultTool(); - mySurfaceArea.deselectAll(); + myToolProvider.loadDefaultTool(); + mySurfaceArea.deselectAll(); - parseFile(new Runnable() { - @Override - public void run() { - showDesignerCard(); - myLayeredPane.repaint(); + parseFile(new Runnable() { + @Override + public void run() { + showDesignerCard(); + myLayeredPane.repaint(); - DesignerToolWindowManager.getInstance(getProject()).refresh(); - } - }); - } - catch (Throwable e) { - showError("Parse error: ", e); - } + DesignerToolWindowManager.getInstance(getProject()).refresh(); + } + }); } - private void parseFile(final Runnable runnable) throws Exception { + private void parseFile(final Runnable runnable) { + myParseTime = true; final ModelParser parser = new ModelParser(getProject(), myXmlFile); createRenderer(parser.getLayoutXmlText(), new ThrowableRunnable() { @Override @@ -213,12 +208,15 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { myRootComponent = newRootComponent; myLayeredPane.add(rootPanel, LAYER_COMPONENT); + myParseTime = false; + runnable.run(); } }); } private void updateRenderer() { + myParseTime = true; final String layoutXmlText = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public String compute() { @@ -238,6 +236,8 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { rootView.setImage(mySession.getImage()); ModelParser.updateRootComponent(rootComponent, mySession, rootView); + myParseTime = false; + myLayeredPane.repaint(); DesignerToolWindowManager.getInstance(getProject()).refresh(); @@ -255,7 +255,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { throw exception; } else { - throw new Exception("No session result"); + throw new RenderingException("No session result"); } } } @@ -333,23 +333,17 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { } catch (Throwable e) { showError("Parse error: ", e); + myParseTime = false; } } }); } - catch (RenderingException e) { - // TODO - e.printStackTrace(); - } - catch (AndroidSdkNotConfiguredException e) { - // TODO - e.printStackTrace(); - } catch (final Throwable e) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { showError("Render session error: ", e); + myParseTime = false; } }); } @@ -365,9 +359,21 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { } @Override - public void showError(@NonNls String message, Throwable e) { + protected void configureError(ErrorInfo info) { + if (info.throwable instanceof AndroidSdkNotConfiguredException) { + info.message = "Please configure Android SDK"; + info.stack = false; + } + else if (!(info.throwable instanceof RenderingException)) { + info.show = myParseTime; + info.log = true; + } + } + + @Override + protected void showErrorPage(ErrorInfo info) { removeNativeRoot(); - super.showError(message, e); + super.showErrorPage(info); } public ProfileAction getProfileAction() { diff --git a/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png b/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png new file mode 100644 index 000000000000..66bd0421cb0c Binary files /dev/null and b/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png differ diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java index 0de4c1179468..999c82c33e6a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java @@ -114,7 +114,10 @@ public class ModelParser extends XmlRecursiveElementVisitor { component.setTag(tag); Class layout = metaModel.getLayout(); - if (layout != null) { + if (layout == null) { + component.setLayout(RadViewLayout.INSTANCE); + } + else { component.setLayout(layout.newInstance()); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java index 62c155ea5646..e87ab8732618 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java @@ -19,12 +19,13 @@ import com.android.ide.common.rendering.api.ViewInfo; import com.android.resources.ResourceType; import com.android.sdklib.IAndroidTarget; import com.intellij.android.designer.propertyTable.AttributeProperty; +import com.intellij.android.designer.propertyTable.CompoundProperty; import com.intellij.android.designer.propertyTable.FlagProperty; -import com.intellij.android.designer.propertyTable.PaddingProperty; import com.intellij.android.designer.propertyTable.editors.ResourceDialog; import com.intellij.designer.model.MetaManager; import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; +import com.intellij.designer.model.RadLayout; import com.intellij.designer.propertyTable.Property; import com.intellij.designer.propertyTable.PropertyTable; import com.intellij.openapi.module.Module; @@ -47,6 +48,10 @@ import java.util.*; public class PropertyParser { public static final String KEY = "PROPERTY_PARSER"; + private static final String[] DEFAULT_LAYOUT_PARAMS = {"ViewGroup_Layout"}; + private static final String LAYOUT_PREFIX = "layout_"; + private static final String LAYOUT_MARGIN_PREFIX = "layout_margin"; + private final Module myModule; private MetaManager myMetaManager; private AttributeDefinitions myDefinitions; @@ -90,21 +95,45 @@ public class PropertyParser { if (componentClass.getName().equals("com.android.layoutlib.bridge.MockView")) { componentClass = myClassLoader.loadClass("android.view.View"); } - component.setProperties(load(componentClass, model)); + component.setProperties(loadWidgetProperties(componentClass, model)); } } else { - component.setProperties(load(myClassLoader.loadClass(target), model)); + component.setProperties(loadWidgetProperties(myClassLoader.loadClass(target), model)); + } + + RadComponent parent = component.getParent(); + if (parent != null) { + String[] layoutParams = null; + RadLayout layout = parent.getLayout(); + + if (layout instanceof RadViewLayoutWithData) { + layoutParams = ((RadViewLayoutWithData)layout).getLayoutParams(); + } + else if (parent == parent.getRoot()) { + layoutParams = DEFAULT_LAYOUT_PARAMS; + } + + if (layoutParams != null) { + List properties = loadLayoutProperties(layoutParams, 0); + + if (!properties.isEmpty()) { + properties = new ArrayList(properties); + properties.addAll(component.getProperties()); + component.setProperties(properties); + } + } } } - private List load(Class componentClass, MetaModel model) throws Exception { + private List loadWidgetProperties(Class componentClass, MetaModel model) throws Exception { String component = componentClass.getSimpleName(); List properties = myCachedProperties.get(component); if (properties == null) { properties = new ArrayList(); + myCachedProperties.put(component, properties); StyleableDefinition definitions = myDefinitions.getStyleableByName(component); if (definitions != null) { @@ -116,7 +145,7 @@ public class PropertyParser { Property property; if ("padding".equals(name) && "View".equals(component)) { - property = padding = new PaddingProperty(name, definition); + property = padding = new CompoundProperty(name, definition); } else if (formats.contains(AttributeFormat.Flag)) { property = new FlagProperty(name, definition); @@ -151,7 +180,8 @@ public class PropertyParser { superComponentClass = myClassLoader.loadClass("android.view.View"); } - List superProperties = load(superComponentClass, myMetaManager.getModelByTarget(superComponentClass.getName())); + List superProperties = loadWidgetProperties(superComponentClass, + myMetaManager.getModelByTarget(superComponentClass.getName())); for (Property superProperty : superProperties) { if (PropertyTable.findProperty(properties, superProperty) == -1) { if (model == null) { @@ -190,8 +220,79 @@ public class PropertyParser { } }); } + } + return properties; + } + + private List loadLayoutProperties(String[] components, int index) throws Exception { + String component = components[index]; + + List properties = myCachedProperties.get(component); + + if (properties == null) { + properties = new ArrayList(); myCachedProperties.put(component, properties); + + StyleableDefinition definitions = myDefinitions.getStyleableByName(component); + if (definitions != null) { + Property margin = null; + + for (AttributeDefinition definition : definitions.getAttributes()) { + String name = definition.getName(); + boolean important = true; + Set formats = definition.getFormats(); + Property property; + + if (name.startsWith(LAYOUT_MARGIN_PREFIX) && name.length() > LAYOUT_MARGIN_PREFIX.length()) { + name = name.substring(LAYOUT_PREFIX.length()); + important = false; + } + else if (name.startsWith(LAYOUT_PREFIX)) { + name = "layout:" + name.substring(LAYOUT_PREFIX.length()); + } + + if ("layout:margin".equals(name) && "ViewGroup_MarginLayout".equals(component)) { + property = margin = new CompoundProperty(name, definition); + } + else if (formats.contains(AttributeFormat.Flag)) { + property = new FlagProperty(name, definition); + } + else { + property = new AttributeProperty(name, definition); + } + + property.setImportant(important); + properties.add(property); + } + + if (margin != null) { + List children = margin.getChildren(null); + children.add(PropertyTable.extractProperty(properties, "marginLeft")); + children.add(PropertyTable.extractProperty(properties, "marginTop")); + children.add(PropertyTable.extractProperty(properties, "marginRight")); + children.add(PropertyTable.extractProperty(properties, "marginBottom")); + children.add(PropertyTable.extractProperty(properties, "marginStart")); + children.add(PropertyTable.extractProperty(properties, "marginEnd")); + } + } + + if (++index < components.length) { + for (Property property : loadLayoutProperties(components, index)) { + if (PropertyTable.findProperty(properties, property) == -1) { + properties.add(property); + } + } + } + + if (!properties.isEmpty()) { + Collections.sort(properties, new Comparator() { + @Override + public int compare(Property p1, Property p2) { + return p1.getName().compareTo(p2.getName()); + } + }); + } } return properties; diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java new file mode 100644 index 000000000000..1f97e251d2b7 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.model; + +import com.intellij.designer.designSurface.ComponentDecorator; +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; + +import javax.swing.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RadFrameLayout extends RadViewLayoutWithData { + private static final String[] LAYOUT_PARAMS = {"FrameLayout_Layout", "ViewGroup_MarginLayout"}; + + @Override + public String[] getLayoutParams() { + return LAYOUT_PARAMS; + } + + @Override + public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { + return super.getChildSelectionDecorator(component, selection); // TODO: Auto-generated method stub + } + + @Override + public EditOperation processChildOperation(OperationContext context) { + return super.processChildOperation(context); // TODO: Auto-generated method stub + } + + @Override + public void addSelectionActions(DesignerEditorPanel designer, + DefaultActionGroup actionGroup, + JComponent shortcuts, + List selection) { + super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java index e6cbf4533c44..19e04a31053a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java @@ -30,7 +30,14 @@ import java.util.List; /** * @author Alexander Lobas */ -public class RadLinearLayout extends RadViewLayout { +public class RadLinearLayout extends RadViewLayoutWithData { + private static final String[] LAYOUT_PARAMS = {"LinearLayout_Layout", "ViewGroup_MarginLayout"}; + + @Override + public String[] getLayoutParams() { + return LAYOUT_PARAMS; + } + @Override public EditOperation processChildOperation(OperationContext context) { if (context.isCreate()) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java index 163178a83053..c18661f35f0d 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java @@ -68,6 +68,8 @@ public class RadScrollViewComponent extends RadViewComponent { scrollContainer.getTag().setName(scrollContainer.getMetaModel().getTag()); } }); + + // TODO: maybe reload properties } }); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java new file mode 100644 index 000000000000..af4d30984129 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.model; + +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; + +import javax.swing.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RadViewGroupComponent extends RadViewComponent { + @Override + public void addSelectionActions(DesignerEditorPanel designer, + DefaultActionGroup actionGroup, + JComponent shortcuts, + List selection) { + super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java index 97ff2f279b70..f26a67c7bf49 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java @@ -27,7 +27,9 @@ import java.util.List; * @author Alexander Lobas */ public class RadViewLayout extends RadLayout { - @Override + public static final RadLayout INSTANCE = new RadViewLayout(); + + @Override public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { return new NonResizeSelectionDecorator(Color.RED, 1); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java new file mode 100644 index 000000000000..ca1af9c2692d --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.model; + +/** + * @author Alexander Lobas + */ +public abstract class RadViewLayoutWithData extends RadViewLayout { + public abstract String[] getLayoutParams(); +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml index 85f7bcaeebab..a91e9ba6d1cd 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml +++ b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml @@ -13,7 +13,6 @@ @@ -21,7 +20,6 @@ @@ -567,7 +565,6 @@ @@ -587,7 +584,6 @@ @@ -608,7 +604,6 @@ @@ -629,7 +624,6 @@ @@ -647,7 +641,6 @@ @@ -665,7 +658,6 @@ @@ -689,7 +681,6 @@ @@ -728,7 +719,6 @@ @@ -748,7 +738,6 @@ @@ -806,7 +795,6 @@ @@ -826,7 +814,6 @@ @@ -846,7 +833,6 @@ @@ -864,7 +850,6 @@ @@ -884,7 +869,6 @@ @@ -999,7 +983,7 @@ - @@ -1020,6 +1004,26 @@ + + + + + + + + + + ]]> + + + @@ -1077,6 +1081,7 @@ + diff --git a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java index beac64cdd0e6..dce09b2fd85c 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java +++ b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java @@ -32,8 +32,6 @@ import com.intellij.openapi.roots.ModuleRootListener; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Tag; -import org.jetbrains.android.sdk.AndroidPlatform; -import org.jetbrains.android.sdk.AndroidSdkAdditionalData; import org.jetbrains.android.sdk.AndroidSdkType; import org.jetbrains.android.uipreview.LayoutDeviceManager; diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/PaddingProperty.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/CompoundProperty.java similarity index 86% rename from plugins/android-designer/src/com/intellij/android/designer/propertyTable/PaddingProperty.java rename to plugins/android-designer/src/com/intellij/android/designer/propertyTable/CompoundProperty.java index 9981f7ceb9c4..5a0b3f4936e0 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/PaddingProperty.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/CompoundProperty.java @@ -27,10 +27,10 @@ import java.util.List; /** * @author Alexander Lobas */ -public class PaddingProperty extends AttributeProperty { +public class CompoundProperty extends AttributeProperty { private List myChildren = new ArrayList(); - public PaddingProperty(@NotNull String name, @NotNull AttributeDefinition definition) { + public CompoundProperty(@NotNull String name, @NotNull AttributeDefinition definition) { super(name, definition); } @@ -41,7 +41,7 @@ public class PaddingProperty extends AttributeProperty { @Override public Property createForNewPresentation() { - PaddingProperty property = new PaddingProperty(getName(), myDefinition); + CompoundProperty property = new CompoundProperty(getName(), myDefinition); List children = property.getChildren(null); for (Property childProperty : myChildren) { children.add(childProperty.createForNewPresentation()); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java index 0720446f5288..827e177c5930 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java @@ -30,9 +30,9 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { } @Override - public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + public ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk) || AndroidJpsUtil.isLightBuild(context)) { - return ModuleLevelBuilder.ExitCode.OK; + return ExitCode.NOTHING_DONE; } try { @@ -48,6 +48,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { final AndroidFileSetStorage storage = new AndroidFileSetStorage(context.getDataManager().getDataStorageRoot(), "libs_packaging"); try { + boolean doneSomething = false; for (Module module : chunk.getModules()) { final AndroidFacet facet = AndroidJpsUtil.getFacet(module); if (facet == null || !facet.isLibrary()) { @@ -82,7 +83,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { if (subdirs.size() > 0) { context.processMessage(new ProgressMessage(AndroidJpsBundle.message("android.jps.progress.library.packaging", module.getName()))); final File outputJarFile = new File(outputDirectoryForPackagedFiles, AndroidCommonUtils.CLASSES_JAR_FILE_NAME); - + doneSomething = true; try { AndroidCommonUtils.packClassFilesIntoJar(ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.toStringArray(subdirs), outputJarFile); storage.update(module.getName(), newState); @@ -94,7 +95,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { } } } - return success ? ModuleLevelBuilder.ExitCode.OK : ModuleLevelBuilder.ExitCode.ABORT; + return success ? (doneSomething? ExitCode.OK : ExitCode.NOTHING_DONE) : ExitCode.ABORT; } finally { storage.close(); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java index c3f8d80ef2cd..e9ef804f1eef 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java @@ -61,7 +61,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder { @Override public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk)) { - return ModuleLevelBuilder.ExitCode.OK; + return ExitCode.NOTHING_DONE; } try { diff --git a/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java b/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java index cd47db4f160f..563eb772b0ff 100644 --- a/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java +++ b/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java @@ -78,7 +78,7 @@ public abstract class AndroidTestCase extends UsefulTestCase { public void setUp() throws Exception { super.setUp(); - final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(); + final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class); tuneModule(moduleFixtureBuilder, myFixture.getTempDirPath()); diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java index 2c6ee20e6da2..50b9e37c84c4 100644 --- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java @@ -49,7 +49,7 @@ public class AndroidLibraryProjectTest extends UsefulTestCase { @Override public void setUp() throws Exception { super.setUp(); - final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(); + final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); myFixture.enableInspections(AndroidDomInspection.class); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java index b3bc6111df5d..9467e665d90b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -207,8 +207,7 @@ public class CvsHistoryProvider implements VcsHistoryProvider { } private static VcsRevisionNumber getCurrentRevision(FilePath filePath) { - final Entry entryFor = CvsEntriesManager.getInstance().getEntryFor(filePath.getVirtualFileParent(), - filePath.getName()); + final Entry entryFor = CvsEntriesManager.getInstance().getEntryFor(filePath.getVirtualFileParent(), filePath.getName()); if (entryFor == null) { return new CvsRevisionNumber("0"); } @@ -219,13 +218,13 @@ public class CvsHistoryProvider implements VcsHistoryProvider { @Nullable public List createRevisions(final FilePath filePath) { - final ArrayList result = new ArrayList(); final File file = filePath.getIOFile(); final VirtualFile root = CvsVfsUtil.refreshAndFindFileByIoFile(file.getParentFile()); // check if we have a history pane open for a file in a package which has just been deleted if (root == null) return null; final LocalPathIndifferentLogOperation logOperation = new LocalPathIndifferentLogOperation(file); final CvsOperationExecutor executor = new CvsOperationExecutor(myProject); + final ArrayList result = new ArrayList(); executor.performActionSync(new CommandCvsHandler(CvsBundle.message("operation.name.load.file.content"), logOperation), new CvsOperationExecutorCallback() { public void executionFinished(boolean successfully) { @@ -247,6 +246,7 @@ public class CvsHistoryProvider implements VcsHistoryProvider { } } }); + Collections.sort(result, VcsFileRevisionComparator.INSTANCE); return result; } @@ -306,12 +306,19 @@ public class CvsHistoryProvider implements VcsHistoryProvider { } private static List sortRevisions(List revisionsList) { - Collections.sort(revisionsList, new Comparator() { - public int compare(VcsFileRevision rev1, VcsFileRevision rev2) { - return VcsHistoryUtil.compare(rev1, rev2); - } - }); + Collections.sort(revisionsList, VcsFileRevisionComparator.INSTANCE); return revisionsList; } } + + private static class VcsFileRevisionComparator implements Comparator { + + public static final VcsFileRevisionComparator INSTANCE = new VcsFileRevisionComparator(); + + private VcsFileRevisionComparator() {} + + public int compare(VcsFileRevision rev1, VcsFileRevision rev2) { + return VcsHistoryUtil.compare(rev2, rev1); + } + } } diff --git a/plugins/devkit/devkit.iml b/plugins/devkit/devkit.iml index 47d21923aa17..f2f207869c5a 100644 --- a/plugins/devkit/devkit.iml +++ b/plugins/devkit/devkit.iml @@ -26,6 +26,7 @@ + diff --git a/plugins/devkit/src/module/PluginModuleType.java b/plugins/devkit/src/module/PluginModuleType.java index 1336a52594c5..59b4f93aad08 100644 --- a/plugins/devkit/src/module/PluginModuleType.java +++ b/plugins/devkit/src/module/PluginModuleType.java @@ -19,6 +19,7 @@ import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.module.*; +import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; @@ -153,4 +154,15 @@ public class PluginModuleType extends ModuleType { public boolean isValidSdk(final Module module, final Sdk projectSdk) { return JavaModuleType.isValidJavaSdk(module); } + + public static Module[] getAllPluginModules(final Project project) { + List modules = new ArrayList(); + Module[] allModules = ModuleManager.getInstance(project).getModules(); + for (Module module : allModules) { + if (get(module) == getInstance()) { + modules.add(module); + } + } + return modules.toArray(new Module[modules.size()]); + } } \ No newline at end of file diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java index 07d46ffd7de4..9501558fb101 100644 --- a/plugins/devkit/src/projectRoots/IdeaJdk.java +++ b/plugins/devkit/src/projectRoots/IdeaJdk.java @@ -46,6 +46,7 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -183,17 +184,18 @@ public class IdeaJdk extends SdkType implements JavaSdkType { private static VirtualFile[] getIdeaLibrary(String home) { ArrayList result = new ArrayList(); - appendIdeaLibrary(home + File.separator + LIB_DIR_NAME, null, result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JAVAEE_DIR + File.separator + LIB_DIR_NAME, "javaee-impl.jar", - result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JSF_DIR + File.separator + LIB_DIR_NAME, "jsf-impl.jar", result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + PERSISTENCE_SUPPORT + File.separator + LIB_DIR_NAME, "persistence-impl.jar", result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + DATABASE_DIR + File.separator + LIB_DIR_NAME, "database-impl.jar", result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + CSS_DIR + File.separator + LIB_DIR_NAME, "css.jar", result); + appendIdeaLibrary(home + File.separator + LIB_DIR_NAME, result, "junit.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JAVAEE_DIR + File.separator + LIB_DIR_NAME, result, "javaee-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JSF_DIR + File.separator + LIB_DIR_NAME, result, "jsf-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + PERSISTENCE_SUPPORT + File.separator + LIB_DIR_NAME, result, "persistence-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + DATABASE_DIR + File.separator + LIB_DIR_NAME, result, "database-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + CSS_DIR + File.separator + LIB_DIR_NAME, result, "css.jar"); return VfsUtil.toVirtualFileArray(result); } - private static void appendIdeaLibrary(final String path, @Nullable @NonNls final String forbidden, final ArrayList result) { + private static void appendIdeaLibrary(final String path, + final ArrayList result, + @NonNls final String... forbidden) { final JarFileSystem jfs = JarFileSystem.getInstance(); final File lib = new File(path); if (lib.isDirectory()) { @@ -201,7 +203,7 @@ public class IdeaJdk extends SdkType implements JavaSdkType { if (jars != null) { for (File jar : jars) { @NonNls String name = jar.getName(); - if (jar.isFile() && !name.equals(forbidden) && (name.endsWith(".jar") || name.endsWith(".zip"))) { + if (jar.isFile() && Arrays.binarySearch(forbidden, name) < 0 && (name.endsWith(".jar") || name.endsWith(".zip"))) { result.add(jfs.findFileByPath(jar.getPath() + JarFileSystem.JAR_SEPARATOR)); } } diff --git a/plugins/devkit/src/run/PluginConfigurationType.java b/plugins/devkit/src/run/PluginConfigurationType.java index 7d1641fc5614..a40431a6604b 100644 --- a/plugins/devkit/src/run/PluginConfigurationType.java +++ b/plugins/devkit/src/run/PluginConfigurationType.java @@ -26,6 +26,7 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.module.PluginModuleType; import javax.swing.*; import java.io.File; @@ -50,7 +51,7 @@ public class PluginConfigurationType implements ConfigurationType { public RunConfiguration createConfiguration(String name, RunConfiguration template) { final PluginRunConfiguration pluginRunConfiguration = (PluginRunConfiguration)template; if (pluginRunConfiguration.getModule() == null) { - final Module[] modules = pluginRunConfiguration.getModules(); + final Module[] modules = PluginModuleType.getAllPluginModules(pluginRunConfiguration.getProject()); if (modules.length > 0){ pluginRunConfiguration.setModule(modules[0]); } diff --git a/plugins/devkit/src/run/PluginRunConfiguration.java b/plugins/devkit/src/run/PluginRunConfiguration.java index 1a0f22c0bad3..f8fe6a24f2e7 100644 --- a/plugins/devkit/src/run/PluginRunConfiguration.java +++ b/plugins/devkit/src/run/PluginRunConfiguration.java @@ -25,7 +25,6 @@ import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdkType; @@ -39,14 +38,11 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; -import org.jetbrains.idea.devkit.module.PluginModuleType; import org.jetbrains.idea.devkit.projectRoots.IdeaJdk; import org.jetbrains.idea.devkit.projectRoots.Sandbox; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; public class PluginRunConfiguration extends RunConfigurationBase implements ModuleRunConfiguration { private Module myModule; @@ -246,14 +242,8 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu @NotNull public Module[] getModules() { - List modules = new ArrayList(); - Module[] allModules = ModuleManager.getInstance(getProject()).getModules(); - for (Module module : allModules) { - if (ModuleType.get(module) == PluginModuleType.getInstance()) { - modules.add(module); - } - } - return modules.toArray(new Module[modules.size()]); + final Module module = getModule(); + return module != null ? new Module[]{module} : Module.EMPTY_ARRAY; } public void readExternal(Element element) throws InvalidDataException { diff --git a/plugins/devkit/src/run/PluginRunConfigurationEditor.java b/plugins/devkit/src/run/PluginRunConfigurationEditor.java index 6abca2f12397..8b4ae5bdf778 100644 --- a/plugins/devkit/src/run/PluginRunConfigurationEditor.java +++ b/plugins/devkit/src/run/PluginRunConfigurationEditor.java @@ -18,14 +18,13 @@ package org.jetbrains.idea.devkit.run; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.LogFileOptions; import com.intellij.execution.ui.AlternativeJREPanel; -import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ui.configuration.ModulesCombobox; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.ui.PanelWithAnchor; import com.intellij.ui.RawCommandLineEditor; @@ -35,6 +34,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.module.PluginModuleType; import org.jetbrains.idea.devkit.projectRoots.IdeaJdk; import org.jetbrains.idea.devkit.projectRoots.Sandbox; @@ -49,9 +49,7 @@ import java.io.IOException; import java.util.ArrayList; public class PluginRunConfigurationEditor extends SettingsEditor implements PanelWithAnchor { - - private DefaultComboBoxModel myModulesModel = new DefaultComboBoxModel(); - private final JComboBox myModules = new JComboBox(myModulesModel); + private final ModulesCombobox myModules = new ModulesCombobox(); private final JBLabel myModuleLabel = new JBLabel(ExecutionBundle.message("application.configuration.use.classpath.and.jdk.of.module.label")); private final LabeledComponent myVMParameters = new LabeledComponent(); private final LabeledComponent myProgramParameters = new LabeledComponent(); @@ -73,9 +71,10 @@ public class PluginRunConfigurationEditor extends SettingsEditor(myModules.getRenderer()) { - @Override - public void customize(JList list, final Module module, int index, boolean selected, boolean hasFocus) { - if (module != null) { - setText(module.getName()); - setIcon(ModuleType.get(module).getNodeIcon(true)); - } - } - }); + myModules.fillModules(myPRC.getProject(), PluginModuleType.getInstance()); JPanel wholePanel = new JPanel(new GridBagLayout()); myVMParameters.setText(DevKitBundle.message("vm.parameters")); myVMParameters.setComponent(new RawCommandLineEditor()); diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy b/plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy new file mode 100644 index 000000000000..46a5a8367298 --- /dev/null +++ b/plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.devkit.codeInsight + +import com.intellij.codeInsight.completion.CompletionAutoPopupTestCase + +/** + * @author peter + */ +class PluginXmlAutoPopupTest extends CompletionAutoPopupTestCase { + + public void "test autopopup for class references"() { + myFixture.addClass("public class FooFooFooFooFoo { }"); + myFixture.configureByText 'plugin.xml', ''' + + + + + +''' + type 'o' + assert lookup + assert myFixture.lookupElementStrings == ['FooFooFooFooFoo'] + } + + public void "test no autopopup when only word completion is available"() { + myFixture.configureByText 'plugin.xml', ''' + + + + + +''' + type 'e' + assert !lookup + } + +} diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java index 05dfc5829a4b..d7972ddbb3fc 100644 --- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java +++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.ArrayUtil; public class EclipseLibrariesModificationsTest extends EclipseVarsTest { @@ -38,22 +39,8 @@ public class EclipseLibrariesModificationsTest extends EclipseVarsTest { final Project project = getProject(); final String path = project.getBaseDir().getPath() + "/test"; final Module module = EclipseClasspathTest.setUpModule(path, project); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); - final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, model.getContentRoots()[0].getParent().getPath()); - final Library library = model.getModuleLibraryTable().createLibrary("created"); - final Library.ModifiableModel libModifiableModel = library.getModifiableModel(); - for (String classRoot : classRoots) { - libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES); - } - for (String sourceRoot : sourceRoots) { - libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES); - } - libModifiableModel.commit(); - model.commit(); - } - }); + PsiTestUtil.addLibrary(module, "created", ModuleRootManager.getInstance(module).getContentRoots()[0].getParent().getPath(), classRoots, + sourceRoots); EclipseClasspathTest.checkModule(project.getBaseDir().getPath() + "/expected", module); } diff --git a/plugins/git4idea/src/git4idea/Notificator.java b/plugins/git4idea/src/git4idea/Notificator.java index c164ac37bfbf..b1b11f4ab7f7 100644 --- a/plugins/git4idea/src/git4idea/Notificator.java +++ b/plugins/git4idea/src/git4idea/Notificator.java @@ -67,7 +67,7 @@ public class Notificator { notify(notificationGroup, title, message, type, null); } - public void notifyError(String title, String message) { + public void notifyError(@NotNull String title, @NotNull String message) { notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, title, message, NotificationType.ERROR, null); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java index 50f1f8b6c625..83412ba7f292 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java @@ -143,7 +143,7 @@ public class GithubCreateGistAction extends DumbAwareAction { response = method.getResponseBodyAsString(); } catch (IOException e1) { - showError(project, "Failed to create gist", null, null, e1); + showError(project, "Failed to create gist", "", null, e1); return; } finally { @@ -155,7 +155,7 @@ public class GithubCreateGistAction extends DumbAwareAction { jsonResponse = new JsonParser().parse(response).getAsJsonObject(); } catch (JsonSyntaxException jse) { - showError(project, "Couldn't parse GitHub response", null, response, jse); + showError(project, "Couldn't parse GitHub response", "", response, jse); return; } @@ -188,7 +188,7 @@ public class GithubCreateGistAction extends DumbAwareAction { } } - private static void showError(@NotNull Project project, @NotNull String title, @Nullable String content, + private static void showError(@NotNull Project project, @NotNull String title, @NotNull String content, @Nullable String details, @Nullable Exception e) { Notificator.getInstance(project).notifyError(title, content); LOG.info("Couldn't parse response as json data: \n" + content + "\n" + details, e); diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java index b5dfe06f98a9..3ec134a45def 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java @@ -2,8 +2,6 @@ package org.jetbrains.plugins.github.ui; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.IconLoader; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.github.GithubSettings; import org.jetbrains.plugins.github.GithubUtil; @@ -29,38 +27,27 @@ public class GitHubSettingsConfigurable implements SearchableConfigurable { return GithubUtil.GITHUB_ICON; } + @NotNull public String getHelpTopic() { return "settings.github"; } public JComponent createComponent() { if (mySettingsPane == null) { - mySettingsPane = new GithubSettingsPanel(); + mySettingsPane = new GithubSettingsPanel(mySettings); } reset(); return mySettingsPane.getPanel(); } public boolean isModified() { - return mySettingsPane != null && (!Comparing.equal(mySettings.getLogin(), mySettingsPane.getLogin()) || - !Comparing.strEqual(mySettings.getPassword(), mySettingsPane.getPassword()) || - !Comparing.equal(mySettings.getHost(), mySettingsPane.getHost())); + return false; } public void apply() throws ConfigurationException { - if (mySettingsPane != null) { - mySettings.setLogin(mySettingsPane.getLogin()); - mySettings.setPassword(mySettingsPane.getPassword()); - mySettings.setHost(mySettingsPane.getHost()); - } } public void reset() { - if (mySettingsPane != null) { - mySettingsPane.setLogin(mySettings.getLogin()); - mySettingsPane.setPassword(mySettings.getPassword()); - mySettingsPane.setHost(mySettings.getHost()); - } } public void disposeUIResources() { diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form index f828dabfa194..043dc84c7ab0 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form @@ -1,6 +1,6 @@
- + @@ -8,36 +8,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -45,55 +18,25 @@ + - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java index 29e352692067..267941384273 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java @@ -16,11 +16,11 @@ package org.jetbrains.plugins.github.ui; import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.HyperlinkAdapter; -import org.jetbrains.plugins.github.GithubUtil; +import org.jetbrains.plugins.github.GithubSettings; import javax.swing.*; import javax.swing.event.HyperlinkEvent; @@ -33,14 +33,11 @@ import java.awt.event.ActionListener; * @date 10/20/10 */ public class GithubSettingsPanel { - private JTextField myLoginTextField; - private JPasswordField myPasswordField; private JTextPane mySignupTextField; private JPanel myPane; private JButton myTestButton; - private JTextField myHostTextField; - public GithubSettingsPanel() { + public GithubSettingsPanel(final GithubSettings settings) { mySignupTextField.addHyperlinkListener(new HyperlinkAdapter() { @Override protected void hyperlinkActivated(final HyperlinkEvent e) { @@ -54,10 +51,12 @@ public class GithubSettingsPanel { myTestButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (GithubUtil.checkCredentials(ProjectManager.getInstance().getDefaultProject(), getHost(), getLogin(), getPassword())){ - Messages.showInfoMessage("Connection successful", "Success"); - } else { - Messages.showErrorDialog("Cannot login to the " + getHost() + " using given credentials", "Failure"); + Project project = ProjectManager.getInstance().getDefaultProject(); + final GithubLoginDialog dialog = new GithubLoginDialog(project); + dialog.show(); + if (dialog.isOK()){ + // the dialog won't let close after pressing OK if the connection is not successful + Messages.showInfoMessage(myPane, "Connection successful", "Success"); } } }); @@ -67,29 +66,5 @@ public class GithubSettingsPanel { return myPane; } - public void setLogin(final String login) { - myLoginTextField.setText(login); - } - - public void setPassword(final String password) { - // Show password as blank if password is empty - myPasswordField.setText(StringUtil.isEmpty(password) ? null : password); - } - - public String getLogin() { - return myLoginTextField.getText().trim(); - } - - public String getPassword() { - return String.valueOf(myPasswordField.getPassword()); - } - - public void setHost(final String host) { - myHostTextField.setText(host); - } - - public String getHost() { - return myHostTextField.getText().trim(); - } } diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 2c6a41287403..0852f2e8fdfe 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -49,7 +49,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { try { final List toCompile = collectChangedFiles(context, chunk); if (toCompile.isEmpty()) { - return ExitCode.OK; + return ExitCode.NOTHING_DONE; } String moduleOutput = getModuleOutput(context, chunk); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java index c327b42e1131..f23d90d93da8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java @@ -94,7 +94,7 @@ public class SuppressForMemberFix extends SuppressIntentionAction { return container != null && context != null && context.getManager().isInProject(context); } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { GrDocCommentOwner container = getContainer(element); assert container != null; if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java index f2e268a51217..bf16de6542e3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java @@ -18,9 +18,7 @@ package org.jetbrains.plugins.groovy.codeInspection.noReturnMethod; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -65,14 +63,33 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { return GroovyInspectionBundle.message("no.return.display.name"); } + public enum ReturnStatus { + mustReturnValue, shouldReturnValue, shouldNotReturnValue; + + public static ReturnStatus getReturnStatus(PsiElement subject) { + if (subject instanceof GrClosableBlock) { + final PsiType inferredReturnType = GroovyExpectedTypesProvider.getExpectedClosureReturnType((GrClosableBlock)subject); + if (inferredReturnType instanceof PsiClassType) { + PsiClass resolved = ((PsiClassType)inferredReturnType).resolve(); + if (resolved != null && !(resolved instanceof PsiTypeParameter)) return mustReturnValue; + } + return inferredReturnType != null && inferredReturnType != PsiType.VOID ? shouldReturnValue : shouldNotReturnValue; + } + else if (subject instanceof GrMethod) { + return ((GrMethod)subject).getReturnTypeElementGroovy() != null && ((GrMethod)subject).getReturnType() != PsiType.VOID + ? mustReturnValue + : shouldNotReturnValue; + } + return shouldNotReturnValue; + } + } + @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean onTheFly) { return new GroovyPsiElementVisitor(new GroovyElementVisitor() { public void visitClosure(GrClosableBlock closure) { super.visitClosure(closure); - - final PsiType expectedClosureType = GroovyExpectedTypesProvider.getExpectedClosureReturnType(closure); - check(closure, problemsHolder, expectedClosureType != null && expectedClosureType != PsiType.VOID); + check(closure, problemsHolder, ReturnStatus.getReturnStatus(closure)); } public void visitMethod(GrMethod method) { @@ -80,72 +97,70 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { final GrOpenBlock block = method.getBlock(); if (block != null) { - final boolean mustReturnValue = method.getReturnTypeElementGroovy() != null && method.getReturnType() != PsiType.VOID; - check(block, problemsHolder, mustReturnValue); + check(block, problemsHolder, ReturnStatus.getReturnStatus(method)); } } }); - } - private static void check(GrCodeBlock block, ProblemsHolder holder, boolean mustReturnValue) { - if (methodMissesSomeReturns(block, mustReturnValue)) { + private static void check(GrCodeBlock block, ProblemsHolder holder, ReturnStatus returnStatus) { + if (methodMissesSomeReturns(block, returnStatus)) { addNoReturnMessage(block, holder); } } - public static boolean methodMissesSomeReturns(GrControlFlowOwner block, boolean mustReturnValue) { - if (!mustReturnValue) { + public static boolean methodMissesSomeReturns(GrControlFlowOwner block, ReturnStatus returnStatus) { + if (returnStatus == ReturnStatus.shouldNotReturnValue) { return false; } - final Ref always = new Ref(true); + final Ref alwaysHaveReturn = new Ref(true); + final Ref sometimesHaveReturn = new Ref(false); final Ref hasExplicitReturn = new Ref(false); - final Ref sometimes = new Ref(false); ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() { @Override public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) { if (instruction instanceof MaybeReturnInstruction) { if (((MaybeReturnInstruction)instruction).mayReturnValue()) { - sometimes.set(true); + sometimesHaveReturn.set(true); } else { - always.set(false); + alwaysHaveReturn.set(false); } return true; } final PsiElement element = instruction.getElement(); if (element instanceof GrReturnStatement) { - sometimes.set(true); + sometimesHaveReturn.set(true); if (returnValue != null) { hasExplicitReturn.set(true); } } else if (instruction instanceof ThrowingInstruction) { - sometimes.set(true); + sometimesHaveReturn.set(true); } else if (element instanceof GrAssertStatement) { - sometimes.set(true); + sometimesHaveReturn.set(true); int count = 0; for (Instruction _i : instruction.allSuccessors()) { count++; } if (count <= 1) { - always.set(false); + alwaysHaveReturn.set(false); } } else { - always.set(false); + alwaysHaveReturn.set(false); } return true; } }); - if (!sometimes.get()) { + if (returnStatus == ReturnStatus.mustReturnValue && !sometimesHaveReturn.get()) { return true; } - return sometimes.get() && !always.get(); + return sometimesHaveReturn.get() && !alwaysHaveReturn.get(); } private static void addNoReturnMessage(GrCodeBlock block, ProblemsHolder holder) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java index d010e1b33a83..d114a69b3100 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java @@ -19,11 +19,10 @@ import com.google.common.collect.Maps; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.util.containers.ConcurrentFactoryMap; +import com.intellij.util.containers.ConcurrentSoftHashMap; import org.jetbrains.plugins.groovy.dsl.CustomMembersGenerator; import org.jetbrains.plugins.groovy.dsl.GroovyClassDescriptor; import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor; @@ -41,23 +40,24 @@ public class NonCodeMembersHolder implements CustomMembersHolder { public static final Key DOCUMENTATION = Key.create("GdslDocumentation"); public static final Key DOCUMENTATION_URL = Key.create("GdslDocumentationUrl"); private final List myMethods = new ArrayList(); - private static final Key, NonCodeMembersHolder>>> CACHED_HOLDERS = Key.create("CACHED_HOLDERS"); public static NonCodeMembersHolder generateMembers(Set methods, final PsiFile place) { - return CachedValuesManager.getManager(place.getProject()).getCachedValue(place, CACHED_HOLDERS, new CachedValueProvider, NonCodeMembersHolder>>() { - public Result, NonCodeMembersHolder>> compute() { - final ConcurrentFactoryMap, NonCodeMembersHolder> map = new ConcurrentFactoryMap, NonCodeMembersHolder>() { - @Override - protected NonCodeMembersHolder create(Set key) { - return new NonCodeMembersHolder(key, place); - } - }; + Map, NonCodeMembersHolder> map = CachedValuesManager.getManager(place.getProject()).getCachedValue( + place, new CachedValueProvider, NonCodeMembersHolder>>() { + public Result, NonCodeMembersHolder>> compute() { + final Map, NonCodeMembersHolder> map = new ConcurrentSoftHashMap, NonCodeMembersHolder>(); return Result.create(map, PsiModificationTracker.MODIFICATION_COUNT); } - }, false).get(methods); + }); + + NonCodeMembersHolder result = map.get(methods); + if (result == null) { + map.put(methods, result = new NonCodeMembersHolder(methods, place)); + } + return result; } - public NonCodeMembersHolder(Set data, PsiElement place) { + private NonCodeMembersHolder(Set data, PsiElement place) { final PsiManager manager = place.getManager(); for (Map prop : data) { String name = String.valueOf(prop.get("name")); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java index 895f178c762a..2869eb12bcf2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java @@ -43,6 +43,7 @@ public class GroovyCodeStyleSettings extends CustomCodeStyleSettings { public boolean SPACE_IN_NAMED_ARGUMENT = true; public boolean ALIGN_MULTILINE_LIST_OR_MAP = false; + public boolean SPACE_WITHIN_LIST_OR_MAP = false; public GroovyCodeStyleSettings(CodeStyleSettings container) { super("GroovyCodeStyleSettings", container); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java index 6cd8df934c1a..a93b3cf1549b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java @@ -115,6 +115,7 @@ public class GroovyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSe "SPACE_WITHIN_ANNOTATION_PARENTHESES" ); consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_IN_NAMED_ARGUMENT", "In named argument after ':'", CodeStyleSettingsCustomizable.SPACES_OTHER); + consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_WITHIN_LIST_OR_MAP", "List and maps literals", CodeStyleSettingsCustomizable.SPACES_WITHIN); return; } consumer.showAllStandardOptions(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java index 970d869780a1..46805d001b79 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java @@ -546,7 +546,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitListOrMap(GrListOrMap listOrMap) { if (myType1 == mLBRACK || myType2 == mRBRACK) { - createSpaceInCode(mySettings.SPACE_WITHIN_BRACKETS); + createSpaceInCode(myGroovySettings.SPACE_WITHIN_LIST_OR_MAP); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index 574c5c9d4e1b..b77bd7c933fc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.folding; import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; +import com.intellij.codeInsight.folding.impl.JavaFoldingBuilder; import com.intellij.lang.ASTNode; import com.intellij.lang.folding.CustomFoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; @@ -24,10 +25,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiAnonymousClass; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; +import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.hash.HashSet; @@ -197,7 +195,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy int start = first.getTextRange().getStartOffset(); int end = marker.getTextRange().getEndOffset(); int tail = "import ".length(); - if (start + tail < end) { + if (start + tail < end && !JavaFoldingBuilder.hasErrorElementsNearby(first.getContainingFile(), start, end)) { descriptors.add(new FoldingDescriptor(first.getNode(), new TextRange(start + tail, end))); } } @@ -215,6 +213,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy return text.contains("\n") || text.contains("\r") || text.contains("\r\n"); } + @Nullable @Override protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) { final IElementType elemType = node.getElementType(); @@ -245,8 +244,21 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy return settings.isCollapseImports(); } - if (node.getElementType() == GROOVY_DOC_COMMENT) { - return settings.isCollapseJavadocs(); + if (node.getElementType() == GROOVY_DOC_COMMENT || node.getElementType() == mML_COMMENT) { + PsiElement element = node.getPsi(); + PsiElement parent = element.getParent(); + if (parent instanceof GroovyFile) { + PsiElement firstChild = parent.getFirstChild(); + if (firstChild instanceof PsiWhiteSpace) { + firstChild = firstChild.getNextSibling(); + } + if (element.equals(firstChild)) { + return settings.isCollapseFileHeader(); + } + } + if (node.getElementType() == GROOVY_DOC_COMMENT) { + return settings.isCollapseJavadocs(); + } } if ((node.getElementType() == OPEN_BLOCK || node.getElementType() == CONSTRUCTOR_BODY) && node.getTreeParent().getElementType() == METHOD_DEFINITION) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java index 32355663ea49..f47fbf22631a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java @@ -247,7 +247,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { ExpressionContext extended = context.extend(); extended.searchForLocalVarsToWrap((GroovyPsiElement)scriptFile); new CodeBlockGenerator(builder, extended, exitPoints) - .visitStatementOwner((GroovyFile)scriptFile, MissingReturnInspection.methodMissesSomeReturns((GroovyFile)scriptFile, true)); + .visitStatementOwner((GroovyFile)scriptFile, MissingReturnInspection.methodMissesSomeReturns((GroovyFile)scriptFile, MissingReturnInspection.ReturnStatus.mustReturnValue)); builder.append("\n}\n"); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java index b526545ce770..ff4ac8cd4acc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java @@ -87,7 +87,7 @@ public class ClosureGenerator { Collection myExitPoints = ControlFlowUtils.collectReturns(block); boolean shouldInsertReturnNull = - !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, false); + !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.shouldNotReturnValue); new CodeBlockGenerator(builder, context.extend(), myExitPoints).generateCodeBlock(block, shouldInsertReturnNull); builder.append('\n'); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java index f42e83d4de65..f921633f3d27 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java @@ -101,7 +101,8 @@ public class CodeBlockGenerator extends Generator { if (!method.isConstructor() && returnType != PsiType.VOID) { myExitPoints.addAll(ControlFlowUtils.collectReturns(block)); shouldInsertReturnNull = !(returnType instanceof PsiPrimitiveType) && - MissingReturnInspection.methodMissesSomeReturns(block, method.getReturnTypeElementGroovy() != null); + MissingReturnInspection.methodMissesSomeReturns(block, + MissingReturnInspection.ReturnStatus.getReturnStatus(method)); } if (block != null) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy index 04ee1eab49e1..7df5c8c1830e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy @@ -47,6 +47,25 @@ class GroovyFoldingTest extends LightCodeInsightFixtureTestCase { assert assertNoFolding(myFixture.file.text.indexOf(marker)), marker } + public void testEditingImports() { + configure """ +import java.util.List +import java.util.Map + + +println 'hello' + +class Foo { List a; Map b; } +""" + + assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10) + + myFixture.type 'import ' + myFixture.doHighlighting() + assert !myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10) + } + + void testOpenBlock() { configure '''def foo() {print 'a'} def bar() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy index e85cc9cd0a44..538fac39a666 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy @@ -41,6 +41,7 @@ public class MissingReturnTest extends LightCodeInsightFixtureTestCase { public void testImplicitReturnNull() throws Throwable {doTest();} public void testMissingReturnInClosure() {doTest();} public void testFinally() {doTest();} + public void testClosureWithExplicitExpectedType() {doTest()} private void doTest() { myFixture.enableInspections(new MissingReturnInspection()); diff --git a/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy b/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy new file mode 100644 index 000000000000..d8a58ad50356 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy @@ -0,0 +1,19 @@ +def foo(Closure c) { + return c().substring(1) +} + +foo { + print 2 +} + +foo { + 's' +} + +foo { + if (a) 's' +} + +foo { + if (a) 'a' else 'b' +} diff --git a/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy b/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy index dd8a60c60789..4fc8273eeaee 100644 --- a/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy +++ b/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy @@ -2,7 +2,7 @@ def mkString(def i) {} print([1, 2, 3].collect { mkString(it) -}) +}) print([1, 2, 3].collect { @@ -10,5 +10,5 @@ print([1, 2, 3].collect { }) Closure c1 = { mkString(it)} -Closure c2 = {mkString(it)} +Closure c2 = {mkString(it); if (a) return 2} def c3 = {mkString(it)} \ No newline at end of file diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java index 0c9ecaa47ce9..f674084163a0 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java @@ -41,7 +41,7 @@ class SuppressByCommentOutAction extends SuppressIntentionAction { } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return; element = findJavaCodeUpThere(element); PsiFile file = element.getContainingFile(); diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java index bfb590a18a02..9a2b844f55e4 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java @@ -34,6 +34,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class JUnit4TestResultsSender extends RunListener { + private static final String JUNIT_FRAMEWORK_COMPARISON_NAME = ComparisonFailure.class.getName(); + private static final String ORG_JUNIT_COMPARISON_NAME = "org.junit.ComparisonFailure"; + private static final String ASSERTION_CLASS_NAME = AssertionError.class.getName(); + private static final String ASSERTION_FAILED_CLASS_NAME = "junit.framework.AssertionFailedError"; + private final OutputObjectRegistry myRegistry; private Map myCurrentTestMeters = new HashMap(); private Set myCurrentTests = new HashSet(); @@ -46,7 +51,8 @@ public class JUnit4TestResultsSender extends RunListener { final Description description = failure.getDescription(); final Throwable throwable = failure.getException(); - if (throwable instanceof AssertionError || throwable.getCause() instanceof AssertionError) { + final Throwable cause = throwable.getCause(); + if (isAssertionError(throwable.getClass()) || isAssertionError(cause != null ? cause.getClass() : null)) { // junit4 makes no distinction between errors and failures doAddFailure(description, throwable); } @@ -81,13 +87,25 @@ public class JUnit4TestResultsSender extends RunListener { createExceptionNotification(assertion).createPacket(myRegistry, test).send(); } + private static boolean isComparisonFailure(Throwable throwable) { + final String throwableClassName = throwable.getClass().getName(); + return throwableClassName.equals(JUNIT_FRAMEWORK_COMPARISON_NAME) || throwableClassName.equals(ORG_JUNIT_COMPARISON_NAME); + } + + private static boolean isAssertionError(Class throwableClass) { + if (throwableClass == null) return false; + final String throwableClassName = throwableClass.getName(); + if (throwableClassName.equals(ASSERTION_CLASS_NAME) || throwableClassName.equals(ASSERTION_FAILED_CLASS_NAME)) return true; + return isAssertionError(throwableClass.getSuperclass()); + } + private static PacketFactory createExceptionNotification(Throwable assertion) { if (assertion instanceof KnownException) return ((KnownException)assertion).getPacketFactory(); - if (assertion instanceof ComparisonFailure || assertion instanceof org.junit.ComparisonFailure) { + if (isComparisonFailure(assertion)) { return ComparisonDetailsExtractor.create(assertion); } final Throwable cause = assertion.getCause(); - if (cause instanceof ComparisonFailure || cause instanceof org.junit.ComparisonFailure) { + if (isComparisonFailure(cause)) { try { return ComparisonDetailsExtractor.create(assertion, ComparisonDetailsExtractor.getExpected(cause), ComparisonDetailsExtractor.getActual(cause)); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java index 0b4afdef44d3..7a62e53e9ef9 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.maven.services.artifactory; import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenArtifactInfo; @@ -27,6 +28,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -53,6 +55,9 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { } return result; } + catch (JsonSyntaxException e) { + return Collections.emptyList(); + } catch (Exception e) { throw new IOException(e); } @@ -74,7 +79,7 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { final String name = StringUtil.join(Arrays.asList(template.getGroupId(), template.getArtifactId(), template.getVersion()), ":"); final InputStream stream = new Endpoint.Search.Artifact(url).getArtifactSearchResultJson(name, null).getInputStream(); - final ArtifactoryModel.GavcResults results = gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.GavcResults.class); + final ArtifactoryModel.GavcResults results = stream == null? null : gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.GavcResults.class); if (results != null && results.results != null) { for (ArtifactoryModel.GavcResult result : results.results) { if (!result.uri.endsWith(packaging)) continue; @@ -87,7 +92,7 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { final String searchString = className.endsWith("*") || className.endsWith("?") ? className : className + ".class"; final InputStream stream = new Endpoint.Search.Archive(url).getArchiveSearchResultJson(searchString, null).getInputStream(); - final ArtifactoryModel.ArchiveResults results = gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.ArchiveResults.class); + final ArtifactoryModel.ArchiveResults results = stream == null? null : gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.ArchiveResults.class); if (results != null && results.results != null) { for (ArtifactoryModel.ArchiveResult result : results.results) { for (String uri : result.archiveUris) { @@ -99,6 +104,9 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { } return artifacts; } + catch (JsonSyntaxException e) { + return Collections.emptyList(); + } catch (Exception e) { throw new IOException(e); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java index f038a3d21b14..8698108f9b04 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java @@ -23,9 +23,11 @@ import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import org.jetbrains.idea.maven.services.MavenRepositoryService; import javax.xml.bind.JAXBException; +import javax.xml.bind.UnmarshalException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -64,6 +66,9 @@ public class NexusRepositoryService extends MavenRepositoryService { } return result; } + catch (UnmarshalException e) { + return Collections.emptyList(); + } catch (JAXBException e) { throw new IOException(e); } @@ -74,12 +79,12 @@ public class NexusRepositoryService extends MavenRepositoryService { public List findArtifacts(@NotNull String url, @NotNull MavenArtifactInfo template) throws IOException { try { final String packaging = StringUtil.notNullize(template.getPackaging()); - final ArrayList result = new ArrayList(); final String name = StringUtil.join(Arrays.asList(template.getGroupId(), template.getArtifactId(), template.getVersion()), ":"); final SearchResults results = new Endpoint.DataIndex(url).getArtifactlistAsSearchResults( name, template.getGroupId(), template.getArtifactId(), template.getVersion(), null, template.getClassNames()); boolean tooManyResults = results.isTooManyResults(); final SearchResults.Data data = results.getData(); + final ArrayList result = new ArrayList(); if (data != null) { for (ArtifactType each : data.getArtifact()) { if (!Comparing.equal(each.packaging, packaging)) continue; @@ -89,6 +94,9 @@ public class NexusRepositoryService extends MavenRepositoryService { if (tooManyResults) result.add(null); return result; } + catch (UnmarshalException e) { + return Collections.emptyList(); + } catch (JAXBException e) { throw new IOException(e); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java index 0d1a24f7af83..7776c490de18 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java @@ -76,6 +76,7 @@ public class RepositoryAttachDialog extends DialogWrapper { private TextFieldWithBrowseButton myDirectoryField; private String myFilterString; + private boolean myInUpdate; public RepositoryAttachDialog(Project project, boolean managed, final @Nullable String initialFilter) { super(project, true); @@ -117,7 +118,7 @@ public class RepositoryAttachDialog extends DialogWrapper { @Override public void actionPerformed(ActionEvent e) { final boolean popupVisible = myCombobox.isPopupVisible(); - if (!popupVisible || myCoordinates.isEmpty()) { + if (!myInUpdate && (!popupVisible || myCoordinates.isEmpty())) { performSearch(); } else { @@ -181,6 +182,8 @@ public class RepositoryAttachDialog extends DialogWrapper { if (!force && Comparing.equal(myFilterString, prevFilter)) return; int prevSize = myShownItems.size(); myShownItems.clear(); + + myInUpdate = true; final boolean itemSelected = myCoordinates.containsKey(myFilterString) && Comparing.strEqual((String)myCombobox.getSelectedItem(), myFilterString, false); final boolean filtered; @@ -205,6 +208,7 @@ public class RepositoryAttachDialog extends DialogWrapper { } Collections.sort(myShownItems); ((CollectionComboBoxModel)myCombobox.getModel()).update(); + myInUpdate = false; field.setText(myFilterString); field.setCaretPosition(caret); updateInfoLabel(); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java index 97af461e12a6..3dcbe20edc8f 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java @@ -73,7 +73,7 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase { @Override protected void setUpFixtures() throws Exception { - myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder().getFixture(); + myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).getFixture(); myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(myTestFixture); myFixture.setUp(); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java index aa34ea474344..95f5341069c4 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java @@ -74,6 +74,7 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject); System.out.println("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins")); System.out.println("Indexes: " + instance.getIndices()); + throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + "Indexes: " + instance.getIndices()); } assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java b/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java index 6bbdcace6701..499e1fc8a78f 100644 --- a/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java +++ b/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java @@ -110,7 +110,7 @@ public abstract class PropertySuppressableInspectionBase extends LocalInspection return property != null && property.isValid(); } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiFile file = element.getContainingFile(); if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; @@ -149,7 +149,7 @@ public abstract class PropertySuppressableInspectionBase extends LocalInspection return element.isValid() && element.getContainingFile() instanceof PropertiesFile; } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiFile file = element.getContainingFile(); if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java index 9d214220cfae..f6fb8dbd5458 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java @@ -10,10 +10,12 @@ import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import java.io.File; @@ -23,6 +25,13 @@ import java.util.List; public class SvnCommittedViewTest extends SvnTestCase { + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + SvnConfiguration.getInstance(myProject).DETECT_NESTED_COPIES = false; + } + @Test public void testAdd() throws Exception { enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); @@ -37,6 +46,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -68,6 +78,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -96,6 +107,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -124,6 +136,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -156,6 +169,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -181,6 +195,7 @@ public class SvnCommittedViewTest extends SvnTestCase { verify(runSvn("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch")); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -210,6 +225,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), diff --git a/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java b/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java index 5c8cac947f2d..b3565b8c2bb6 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java +++ b/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java @@ -15,9 +15,7 @@ */ package com.theoryinpractice.testng.inspection; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.*; -import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.LabeledComponent; @@ -171,7 +169,6 @@ public class DependsOnGroupsInspection extends BaseJavaLocalInspectionTool { final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); //correct save settings - ((InspectionProfileImpl)inspectionProfile).isProperSetting(HighlightDisplayKey.find(SHORT_NAME)); InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile); //TODO lesya /* diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java index 15bb312a9e48..bff58a5533db 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java @@ -18,6 +18,7 @@ package com.intellij.uiDesigner.actions; import com.intellij.CommonBundle; import com.intellij.compiler.PsiClassWriter; import com.intellij.compiler.impl.FileSetCompileScope; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.execution.*; import com.intellij.execution.configurations.*; import com.intellij.execution.executors.DefaultRunExecutor; @@ -128,118 +129,124 @@ public final class PreviewFormAction extends AnAction{ final String classPath = OrderEnumerator.orderEntries(module).recursively().getPathsList().getPathsString() + File.pathSeparator + sources.getPathsString() + File.pathSeparator + /* resources bundles */ tempPath; - final ClassLoader loader = Form2ByteCodeCompiler.createClassLoader(classPath); + final InstrumentationClassFinder finder = Form2ByteCodeCompiler.createClassFinder(classPath); - final Document doc = FileDocumentManager.getInstance().getDocument(formFile); - final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(doc.getText(), new CompiledClassPropertiesProvider(loader)); - } - catch (Exception e) { - Messages.showErrorDialog( - module.getProject(), - UIDesignerBundle.message("error.cannot.read.form", formFile.getPath().replace('/', File.separatorChar), e.getMessage()), - CommonBundle.getErrorTitle() - ); - return; - } - - if (rootContainer.getComponentCount() == 0) { - Messages.showErrorDialog( - module.getProject(), - UIDesignerBundle.message("error.cannot.preview.empty.form", formFile.getPath().replace('/', File.separatorChar)), - CommonBundle.getErrorTitle() - ); - return; - } - - setPreviewBindings(rootContainer, CLASS_TO_BIND_NAME); - - // 2. Copy previewer class and all its superclasses into TEMP directory and instrument it. - try { - PreviewNestedFormLoader nestedFormLoader = new PreviewNestedFormLoader(module, tempPath, loader); - - final File tempFile = CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME, true); - //CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$1", true); - CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyExitAction", true); - CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyPackAction", true); - CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MySetLafAction", true); - - Locale locale = Locale.getDefault(); - if (locale.getCountry().length() > 0 && locale.getLanguage().length() > 0) { - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + - "_" + locale.getCountry() + PropertiesFileType.DOT_DEFAULT_EXTENSION); + final Document doc = FileDocumentManager.getInstance().getDocument(formFile); + final LwRootContainer rootContainer; + try { + rootContainer = Utils.getRootContainer(doc.getText(), new CompiledClassPropertiesProvider(finder.getLoader())); } - if (locale.getLanguage().length() > 0) { - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); - } - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + PropertiesFileType.DOT_DEFAULT_EXTENSION); - - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader, nestedFormLoader, true, - new PsiClassWriter(module)); - codeGenerator.patchFile(tempFile); - final FormErrorInfo[] errors = codeGenerator.getErrors(); - if(errors.length != 0){ + catch (Exception e) { Messages.showErrorDialog( module.getProject(), - UIDesignerBundle.message("error.cannot.preview.form", - formFile.getPath().replace('/', File.separatorChar), - errors[0].getErrorMessage()), + UIDesignerBundle.message("error.cannot.read.form", formFile.getPath().replace('/', File.separatorChar), e.getMessage()), CommonBundle.getErrorTitle() ); return; } - } - catch (Exception e) { - LOG.debug(e); - Messages.showErrorDialog( - module.getProject(), - UIDesignerBundle.message("error.cannot.preview.form", formFile.getPath().replace('/', File.separatorChar), - e.getMessage() != null ? e.getMessage() : e.toString()), - CommonBundle.getErrorTitle() - ); - return; - } - // 2.5. Copy up-to-date properties files to the output directory. - final HashSet bundleSet = new HashSet(); - FormEditingUtil.iterateStringDescriptors( - rootContainer, - new FormEditingUtil.StringDescriptorVisitor() { - public boolean visit(final IComponent component, final StringDescriptor descriptor) { - if (descriptor.getBundleName() != null) { - bundleSet.add(descriptor.getDottedBundleName()); - } - return true; + if (rootContainer.getComponentCount() == 0) { + Messages.showErrorDialog( + module.getProject(), + UIDesignerBundle.message("error.cannot.preview.empty.form", formFile.getPath().replace('/', File.separatorChar)), + CommonBundle.getErrorTitle() + ); + return; + } + + setPreviewBindings(rootContainer, CLASS_TO_BIND_NAME); + + // 2. Copy previewer class and all its superclasses into TEMP directory and instrument it. + try { + PreviewNestedFormLoader nestedFormLoader = new PreviewNestedFormLoader(module, tempPath, finder); + + final File tempFile = CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME, true); + //CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$1", true); + CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyExitAction", true); + CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyPackAction", true); + CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MySetLafAction", true); + + Locale locale = Locale.getDefault(); + if (locale.getCountry().length() > 0 && locale.getLanguage().length() > 0) { + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + + "_" + locale.getCountry() + PropertiesFileType.DOT_DEFAULT_EXTENSION); } - }); + if (locale.getLanguage().length() > 0) { + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); + } + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + PropertiesFileType.DOT_DEFAULT_EXTENSION); - if (bundleSet.size() > 0) { - HashSet virtualFiles = new HashSet(); - HashSet modules = new HashSet(); - PropertiesReferenceManager manager = PropertiesReferenceManager.getInstance(module.getProject()); - for(String bundleName: bundleSet) { - for(PropertiesFile propFile: manager.findPropertiesFiles(module, bundleName)) { - virtualFiles.add(propFile.getVirtualFile()); - final Module moduleForFile = ModuleUtil.findModuleForFile(propFile.getVirtualFile(), module.getProject()); - if (moduleForFile != null) { - modules.add(moduleForFile); - } + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator( + rootContainer, finder, nestedFormLoader, true, new PsiClassWriter(module) + ); + codeGenerator.patchFile(tempFile); + final FormErrorInfo[] errors = codeGenerator.getErrors(); + if(errors.length != 0){ + Messages.showErrorDialog( + module.getProject(), + UIDesignerBundle.message("error.cannot.preview.form", + formFile.getPath().replace('/', File.separatorChar), + errors[0].getErrorMessage()), + CommonBundle.getErrorTitle() + ); + return; } } - FileSetCompileScope scope = new FileSetCompileScope(virtualFiles, modules.toArray(new Module[modules.size()])); + catch (Exception e) { + LOG.debug(e); + Messages.showErrorDialog( + module.getProject(), + UIDesignerBundle.message("error.cannot.preview.form", formFile.getPath().replace('/', File.separatorChar), + e.getMessage() != null ? e.getMessage() : e.toString()), + CommonBundle.getErrorTitle() + ); + return; + } - CompilerManager.getInstance(module.getProject()).make(scope, new CompileStatusNotification() { - public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { - if (!aborted && errors == 0) { - runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + // 2.5. Copy up-to-date properties files to the output directory. + final HashSet bundleSet = new HashSet(); + FormEditingUtil.iterateStringDescriptors( + rootContainer, + new FormEditingUtil.StringDescriptorVisitor() { + public boolean visit(final IComponent component, final StringDescriptor descriptor) { + if (descriptor.getBundleName() != null) { + bundleSet.add(descriptor.getDottedBundleName()); + } + return true; + } + }); + + if (bundleSet.size() > 0) { + HashSet virtualFiles = new HashSet(); + HashSet modules = new HashSet(); + PropertiesReferenceManager manager = PropertiesReferenceManager.getInstance(module.getProject()); + for(String bundleName: bundleSet) { + for(PropertiesFile propFile: manager.findPropertiesFiles(module, bundleName)) { + virtualFiles.add(propFile.getVirtualFile()); + final Module moduleForFile = ModuleUtil.findModuleForFile(propFile.getVirtualFile(), module.getProject()); + if (moduleForFile != null) { + modules.add(moduleForFile); + } } } - }); + FileSetCompileScope scope = new FileSetCompileScope(virtualFiles, modules.toArray(new Module[modules.size()])); + + CompilerManager.getInstance(module.getProject()).make(scope, new CompileStatusNotification() { + public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { + if (!aborted && errors == 0) { + runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + } + } + }); + } + else { + runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + } } - else { - runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + finally { + finder.releaseResources(); } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java b/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java index b42fd6bf0520..8bcacec4b2ee 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java @@ -17,6 +17,7 @@ package com.intellij.uiDesigner.make; import com.intellij.compiler.PsiClassWriter; import com.intellij.compiler.impl.CompilerUtil; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.*; import com.intellij.openapi.diagnostic.Logger; @@ -50,7 +51,6 @@ import java.io.DataInput; import java.io.File; import java.io.IOException; import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -71,7 +71,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler { } @NotNull - public static URLClassLoader createClassLoader(@NotNull final String classPath){ + public static InstrumentationClassFinder createClassFinder(@NotNull final String classPath){ final ArrayList urls = new ArrayList(); for (StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer.hasMoreTokens();) { final String s = tokenizer.nextToken(); @@ -82,7 +82,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler { throw new RuntimeException(exc); } } - return new URLClassLoader(urls.toArray(new URL[urls.size()]), null); + return new InstrumentationClassFinder(urls.toArray(new URL[urls.size()])); } @Override @@ -274,81 +274,86 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler { List filesToRefresh = new ArrayList(); for (final Module module : module2itemsList.keySet()) { final String classPath = OrderEnumerator.orderEntries(module).recursively().getPathsList().getPathsString(); - final ClassLoader loader = createClassLoader(classPath); + final InstrumentationClassFinder finder = createClassFinder(classPath); - if (GuiDesignerConfiguration.getInstance(project).COPY_FORMS_RUNTIME_TO_OUTPUT) { - final String moduleOutputPath = CompilerPaths.getModuleOutputPath(module, false); - try { - if (moduleOutputPath != null) { - filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(moduleOutputPath, false)); + try { + if (GuiDesignerConfiguration.getInstance(project).COPY_FORMS_RUNTIME_TO_OUTPUT) { + final String moduleOutputPath = CompilerPaths.getModuleOutputPath(module, false); + try { + if (moduleOutputPath != null) { + filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(moduleOutputPath, false)); + } + final String testsOutputPath = CompilerPaths.getModuleOutputPath(module, true); + if (testsOutputPath != null && !testsOutputPath.equals(moduleOutputPath)) { + filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(testsOutputPath, false)); + } } - final String testsOutputPath = CompilerPaths.getModuleOutputPath(module, true); - if (testsOutputPath != null && !testsOutputPath.equals(moduleOutputPath)) { - filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(testsOutputPath, false)); + catch (IOException e) { + addMessage( + context, + UIDesignerBundle.message("error.cannot.copy.gui.designer.form.runtime", module.getName(), e.toString()), + null, CompilerMessageCategory.ERROR); } } - catch (IOException e) { - addMessage( - context, - UIDesignerBundle.message("error.cannot.copy.gui.designer.form.runtime", module.getName(), e.toString()), - null, CompilerMessageCategory.ERROR); + + final ArrayList list = module2itemsList.get(module); + + for (final MyInstrumentationItem item : list) { + //context.getProgressIndicator().setFraction((double)++formsProcessed / (double)items.length); + + final VirtualFile formFile = item.getFormFile(); + context.getProgressIndicator().setText2(formFile.getPresentableUrl()); + + final String text = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public String compute() { + if (!belongsToCompileScope(context, formFile, item.getClassToBindFQname())) { + return null; + } + Document document = FileDocumentManager.getInstance().getDocument(formFile); + return document == null ? null : document.getText(); + } + }); + if (text == null) { + continue; // does not belong to current scope + } + + final LwRootContainer rootContainer; + try { + rootContainer = Utils.getRootContainer(text, new CompiledClassPropertiesProvider(finder.getLoader())); + } + catch (Exception e) { + addMessage(context, UIDesignerBundle.message("error.cannot.process.form.file", e), formFile, CompilerMessageCategory.ERROR); + continue; + } + + final File classFile = VfsUtil.virtualToIoFile(item.getFile()); + LOG.assertTrue(classFile.exists(), classFile.getPath()); + + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator( + rootContainer, finder, new PsiNestedFormLoader(module), false, new PsiClassWriter(module) + ); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + codeGenerator.patchFile(classFile); + } + }); + final FormErrorInfo[] errors = codeGenerator.getErrors(); + final FormErrorInfo[] warnings = codeGenerator.getWarnings(); + for (FormErrorInfo warning : warnings) { + addMessage(context, warning, formFile, CompilerMessageCategory.WARNING); + } + for (FormErrorInfo error : errors) { + addMessage(context, error, formFile, CompilerMessageCategory.ERROR); + } + if (errors.length == 0) { + compiledItems.add(item); + } } } - - final ArrayList list = module2itemsList.get(module); - - for (final MyInstrumentationItem item : list) { - //context.getProgressIndicator().setFraction((double)++formsProcessed / (double)items.length); - - final VirtualFile formFile = item.getFormFile(); - context.getProgressIndicator().setText2(formFile.getPresentableUrl()); - - final String text = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public String compute() { - if (!belongsToCompileScope(context, formFile, item.getClassToBindFQname())) { - return null; - } - Document document = FileDocumentManager.getInstance().getDocument(formFile); - return document == null ? null : document.getText(); - } - }); - if (text == null) { - continue; // does not belong to current scope - } - - final LwRootContainer rootContainer; - try { - rootContainer = Utils.getRootContainer(text, new CompiledClassPropertiesProvider(loader)); - } - catch (Exception e) { - addMessage(context, UIDesignerBundle.message("error.cannot.process.form.file", e), formFile, CompilerMessageCategory.ERROR); - continue; - } - - final File classFile = VfsUtil.virtualToIoFile(item.getFile()); - LOG.assertTrue(classFile.exists(), classFile.getPath()); - - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader, - new PsiNestedFormLoader(module), false, - new PsiClassWriter(module)); - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - codeGenerator.patchFile(classFile); - } - }); - final FormErrorInfo[] errors = codeGenerator.getErrors(); - final FormErrorInfo[] warnings = codeGenerator.getWarnings(); - for (FormErrorInfo warning : warnings) { - addMessage(context, warning, formFile, CompilerMessageCategory.WARNING); - } - for (FormErrorInfo error : errors) { - addMessage(context, error, formFile, CompilerMessageCategory.ERROR); - } - if (errors.length == 0) { - compiledItems.add(item); - } + finally { + finder.releaseResources(); } } CompilerUtil.refreshIOFiles(filesToRefresh); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java b/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java index dbb2443c74a5..fbe4c8aaa86e 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java @@ -17,6 +17,7 @@ package com.intellij.uiDesigner.make; import com.intellij.compiler.PsiClassWriter; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.openapi.module.Module; import com.intellij.uiDesigner.actions.PreviewFormAction; import com.intellij.uiDesigner.compiler.AsmCodeGenerator; @@ -41,13 +42,13 @@ import java.util.Set; */ public class PreviewNestedFormLoader extends PsiNestedFormLoader { private final String myTempPath; - private final ClassLoader myLoader; + private final InstrumentationClassFinder myFinder; private final Set myGeneratedClasses = new HashSet(); - public PreviewNestedFormLoader(final Module module, final String tempPath, final ClassLoader loader) { + public PreviewNestedFormLoader(final Module module, final String tempPath, final InstrumentationClassFinder finder) { super(module); myTempPath = tempPath; - myLoader = loader; + myFinder = finder; } public LwRootContainer loadForm(String formFileName) throws Exception { @@ -82,7 +83,7 @@ public class PreviewNestedFormLoader extends PsiNestedFormLoader { cw.visitEnd(); ByteArrayInputStream bais = new ByteArrayInputStream(cw.toByteArray()); - AsmCodeGenerator acg = new AsmCodeGenerator(rootContainer, myLoader, this, true, new PsiClassWriter(myModule)); + AsmCodeGenerator acg = new AsmCodeGenerator(rootContainer, myFinder, this, true, new PsiClassWriter(myModule)); byte[] data = acg.patchClass(bais); FormErrorInfo[] errors = acg.getErrors(); if (errors.length > 0) { diff --git a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java index 3bc39bccc584..d8ff9f5c68a6 100644 --- a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java +++ b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java @@ -15,14 +15,21 @@ */ package com.intellij.uiDesigner.core; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.PluginPathManager; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.components.JBTabbedPane; import com.intellij.uiDesigner.compiler.AsmCodeGenerator; import com.intellij.uiDesigner.compiler.FormErrorInfo; import com.intellij.uiDesigner.compiler.NestedFormLoader; import com.intellij.uiDesigner.compiler.Utils; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; import com.intellij.uiDesigner.lw.LwRootContainer; +import com.intellij.util.PathUtil; +import com.intellij.util.ui.UIUtil; import junit.framework.TestCase; import org.objectweb.asm.ClassWriter; @@ -32,7 +39,13 @@ import javax.swing.border.TitledBorder; import java.awt.*; import java.io.*; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -41,19 +54,46 @@ import java.util.Map; */ public class AsmCodeGeneratorTest extends TestCase { private MyNestedFormLoader myNestedFormLoader; - private MyClassLoader myClassLoader; + private MyClassFinder myClassFinder; @Override protected void setUp() throws Exception { super.setUp(); myNestedFormLoader = new MyNestedFormLoader(); - myClassLoader = new MyClassLoader(getClass().getClassLoader()); + + final String swingPath = PathUtil.getJarPathForClass(AbstractButton.class); + + java.util.List cp = new ArrayList(); + appendPath(cp, JBTabbedPane.class); + appendPath(cp, UIUtil.class); + appendPath(cp, SystemInfoRt.class); + appendPath(cp, ApplicationManager.class); + appendPath(cp, PathManager.getResourceRoot(this.getClass(), "/messages/UIBundle.properties")); + appendPath(cp, PathManager.getResourceRoot(this.getClass(), "/RuntimeBundle.properties")); + appendPath(cp, GridLayoutManager.class); // forms_rt + myClassFinder = new MyClassFinder( + new URL[] {new File(swingPath).toURI().toURL()}, + cp.toArray(new URL[cp.size()]) + ); + } + + private static void appendPath(Collection container, Class cls) throws MalformedURLException { + final String path = PathUtil.getJarPathForClass(cls); + appendPath(container, path); + } + + private static void appendPath(Collection container, String path) throws MalformedURLException { + container.add(new File(path).toURI().toURL()); } @Override protected void tearDown() throws Exception { - myClassLoader = null; myNestedFormLoader = null; + final MyClassFinder classFinder = myClassFinder; + if (classFinder != null) { + classFinder.releaseResources(); + myClassFinder = null; + } super.tearDown(); } @@ -70,7 +110,7 @@ public class AsmCodeGeneratorTest extends TestCase { String classPath = tmpPath + "/" + className + ".class"; final LwRootContainer rootContainer = loadFormData(formPath); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, myClassLoader, myNestedFormLoader, false, + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, myClassFinder, myNestedFormLoader, false, new ClassWriter(ClassWriter.COMPUTE_FRAMES)); final FileInputStream classStream = new FileInputStream(classPath); try { @@ -109,7 +149,8 @@ public class AsmCodeGeneratorTest extends TestCase { fos.close(); */ - return myClassLoader.doDefineClass(className, patchedData); + myClassFinder.addClassDefinition(className, patchedData); + return myClassFinder.getLoader().loadClass(className); } private static byte[] getVerifiedPatchedData(final AsmCodeGenerator codeGenerator) { @@ -168,10 +209,41 @@ public class AsmCodeGeneratorTest extends TestCase { public void testGridLayout() throws Exception { JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest"); - assertTrue(rootComponent.getLayout() instanceof GridLayoutManager); - GridLayoutManager gridLayout = (GridLayoutManager) rootComponent.getLayout(); - assertEquals(1, gridLayout.getRowCount()); - assertEquals(1, gridLayout.getColumnCount()); + final LayoutManager layout = rootComponent.getLayout(); + assertTrue(isInstanceOf(layout, GridLayoutManager.class.getName())); + + + assertEquals(1, invokeMethod(layout, "getRowCount")); + assertEquals(1, invokeMethod(layout, "getColumnCount")); + } + + private static boolean isInstanceOf(Object object, final String className) throws ClassNotFoundException { + final Class ethalon = object.getClass().getClassLoader().loadClass(className); + return ethalon.isAssignableFrom(object.getClass()); + } + + private static Object invokeMethod(Object obj, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + return invokeMethod(obj, methodName, new Class[0], new Object[0]); + } + + private static Object invokeMethod(Object obj, String methodName, Class[] params, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + final Method method = findMethod(obj.getClass(), methodName, params); + return method.invoke(obj, args); + } + + private static Method findMethod(Class aClass, String methodName, Class[] params) { + try { + final Method method = aClass.getDeclaredMethod(methodName, params); + method.setAccessible(true); + return method; + } + catch (NoSuchMethodException ignored) { + } + final Class parent = aClass.getSuperclass(); + if (parent == null) { + return null; + } + return findMethod(parent, methodName, params); } public void testCardLayout() throws Exception { @@ -193,10 +265,14 @@ public class AsmCodeGeneratorTest extends TestCase { public void testGridConstraints() throws Exception { JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest"); assertEquals(1, rootComponent.getComponentCount()); - GridLayoutManager gridLayout = (GridLayoutManager) rootComponent.getLayout(); - final GridConstraints constraints = gridLayout.getConstraints(0); - assertEquals(1, constraints.getColSpan()); - assertEquals(1, constraints.getRowSpan()); + final LayoutManager layout = rootComponent.getLayout(); + assertTrue(isInstanceOf(layout, GridLayoutManager.class.getName())); + + final Object constraints = invokeMethod(layout, "getConstraints", new Class[] {int.class}, new Object[] {0}); + assertTrue(isInstanceOf(constraints, GridConstraints.class.getName())); + + assertEquals(1, invokeMethod(constraints, "getColSpan")); + assertEquals(1, invokeMethod(constraints, "getRowSpan")); } public void testIntProperty() throws Exception { @@ -341,7 +417,7 @@ public class AsmCodeGeneratorTest extends TestCase { File.separatorChar + "formEmbedding" + File.separatorChar + "Ideadev14081" + File.separatorChar; AsmCodeGenerator embeddedClassGenerator = initCodeGenerator("Embedded.form", "Embedded", testDataPath); byte[] embeddedPatchedData = getVerifiedPatchedData(embeddedClassGenerator); - myClassLoader.doDefineClass("Embedded", embeddedPatchedData); + myClassFinder.addClassDefinition("Embedded", embeddedPatchedData); myNestedFormLoader.registerNestedForm("Embedded.form", testDataPath + "Embedded.form"); AsmCodeGenerator mainClassGenerator = initCodeGenerator("Main.form", "Main", testDataPath); byte[] mainPatchedData = getVerifiedPatchedData(mainClassGenerator); @@ -352,30 +428,34 @@ public class AsmCodeGeneratorTest extends TestCase { fos.close(); */ - final Class mainClass = myClassLoader.doDefineClass("Main", mainPatchedData); + myClassFinder.addClassDefinition("Main", mainPatchedData); + final Class mainClass = myClassFinder.getLoader().loadClass("Main"); Object instance = mainClass.newInstance(); assert instance != null : mainClass; } - private static class MyClassLoader extends ClassLoader { - private final byte[] myTestProperties = Charset.defaultCharset().encode(TEST_PROPERTY_CONTENT).array(); + private static class MyClassFinder extends InstrumentationClassFinder { private static final String TEST_PROPERTY_CONTENT = "test=Test Value\nmnemonic=Mne&monic"; + private final byte[] myTestProperties = Charset.defaultCharset().encode(TEST_PROPERTY_CONTENT).array(); + private final Map myClassData = new HashMap(); - public MyClassLoader(ClassLoader parent) { - super(parent); + private MyClassFinder(URL[] platformUrls, URL[] classpathUrls) { + super(platformUrls, classpathUrls); } - public Class doDefineClass(String name, byte[] data) { - return defineClass(name, data, 0, data.length); + public void addClassDefinition(String name, byte[] bytes) { + myClassData.put(name.replace('.', '/'), bytes); } - @Override - public Class loadClass(String name) throws ClassNotFoundException { - return super.loadClass(name); + protected InputStream lookupClassBeforeClasspath(String internalClassName) { + final byte[] bytes = myClassData.get(internalClassName); + if (bytes != null) { + return new ByteArrayInputStream(bytes); + } + return null; } - @Override - public InputStream getResourceAsStream(String name) { + public InputStream getResourceAsStream(String name) throws IOException { if (name.equals("TestProperties.properties")) { return new ByteArrayInputStream(myTestProperties, 0, TEST_PROPERTY_CONTENT.length()); } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java index c3ffd4db2ad0..94d5ee9aba40 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java @@ -26,6 +26,7 @@ import com.intellij.designer.palette.Item; import com.intellij.ide.palette.impl.PaletteManager; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -41,17 +42,20 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; import java.util.List; /** * @author Alexander Lobas */ public abstract class DesignerEditorPanel extends JPanel implements DataProvider { + private static final Logger LOG = Logger.getInstance("#com.intellij.designer.designSurface.DesignerEditorPanel"); + protected static final Integer LAYER_COMPONENT = JLayeredPane.DEFAULT_LAYER; protected static final Integer LAYER_STATIC_DECORATION = JLayeredPane.POPUP_LAYER; protected static final Integer LAYER_DECORATION = JLayeredPane.DRAG_LAYER; @@ -85,7 +89,9 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider protected ToolProvider myToolProvider; protected EditableArea mySurfaceArea; - private JLabel myErrorLabel; + private JPanel myErrorPanel; + private JLabel myErrorMessage; + private JTextArea myErrorStack; private JPanel myProgressPanel; private AsyncProcessIcon myProgressIcon; @@ -249,8 +255,18 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } private void createErrorCard() { - myErrorLabel = new JLabel(IconLoader.getIcon("/ide/error_notifications.png"), SwingConstants.CENTER); - add(myErrorLabel, ERROR_CARD); + myErrorPanel = new JPanel(new BorderLayout()); + + myErrorMessage = new JLabel(IconLoader.getIcon("/ide/error_notifications.png")); + myErrorMessage.setFont(myErrorMessage.getFont().deriveFont(Font.BOLD)); + myErrorPanel.add(myErrorMessage, BorderLayout.PAGE_START); + + myErrorStack = new JTextArea(50, 20); + myErrorStack.setEditable(false); + + myErrorPanel.add(ScrollPaneFactory.createScrollPane(myErrorStack), BorderLayout.CENTER); + + add(myErrorPanel, ERROR_CARD); } private void createProgressPanel() { @@ -283,16 +299,47 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider myLayeredPane.remove(myProgressPanel); } - public void showError(@NonNls String message, Throwable e) { + public final void showError(@NonNls String message, Throwable e) { + while (e instanceof InvocationTargetException) { + e = e.getCause(); + } + + ErrorInfo info = new ErrorInfo(); + info.message = message; + info.throwable = e; + configureError(info); + + if (info.show) { + showErrorPage(info); + } + if (info.log || ApplicationManagerEx.getApplicationEx().isInternal()) { + LOG.error(message, e); + } + } + + protected abstract void configureError(ErrorInfo info); + + protected void showErrorPage(ErrorInfo info) { hideProgress(); myRootComponent = null; - myErrorLabel.setText(message + e.toString()); + + myErrorMessage.setText(info.message); + + if (info.stack) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + info.throwable.printStackTrace(new PrintStream(stream)); + myErrorStack.setText(stream.toString()); + myErrorStack.setVisible(true); + } + else { + myErrorStack.setText(null); + myErrorStack.setVisible(false); + } + myLayout.show(this, ERROR_CARD); + DesignerToolWindowManager.getInstance(getProject()).refresh(); repaint(); - if (ApplicationManagerEx.getApplicationEx().isInternal()) { - e.printStackTrace(); - } } public abstract String getPlatformTarget(); @@ -359,7 +406,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } public JComponent getPreferredFocusedComponent() { - return myDesignerCard.isVisible() ? myGlassLayer : myErrorLabel; + return myDesignerCard.isVisible() ? myGlassLayer : myErrorPanel; } public RadComponent getRootComponent() { @@ -519,4 +566,12 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } } } + + public static final class ErrorInfo { + public String message; + public Throwable throwable; + public boolean show = true; + public boolean stack = true; + public boolean log; + } } \ No newline at end of file diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 1a51ab4d3574..508ae6ee32c8 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -164,6 +164,7 @@ error.exception.while.reloading=Exception while reloading classes : {0} : {1} status.hotswap.loaded.classes.up.to.date=Loaded classes are up to date. Nothing to reload error.io.error=I/O error status.classes.reloaded={0,number} {0,choice, 0#classes|1#class|2#classes} reloaded +status.classes.not.all.versions.reloaded=For {0} of {1} {1,choice, 1#class|2#classes} not all versions were reloaded error.cannot.create.void.value=Cannot create void value warning.range.too.big=Range specified is too big. {0} needs too much resources to perform requested operation. Are you sure you want to continue? title.range.too.big=Range is Too Big diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e30a42bfee3b..1dfda1b79956 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -297,6 +297,9 @@ + + diff --git a/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java b/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java index b24e352313a1..92aaedede5a5 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java @@ -178,6 +178,7 @@ public class BaseDomElementNode extends AbstractDomElementNode { return consolidated; } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myDomElement}; } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java b/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java index 83fba1184617..ea8ca192df60 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java @@ -28,6 +28,7 @@ import com.intellij.util.xml.highlighting.DomElementAnnotationsManager; import com.intellij.util.xml.highlighting.DomElementProblemDescriptor; import com.intellij.util.xml.highlighting.DomElementsProblemsHolder; import com.intellij.util.xml.reflect.DomCollectionChildDescription; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.ArrayList; @@ -60,6 +61,7 @@ public class DomElementsGroupNode extends AbstractDomElementNode { return simpleNodes.toArray(new SimpleNode[simpleNodes.size()]); } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myParentElement, myChildrenTagName}; } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java b/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java index 77b161179468..d71a64c4692d 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java @@ -20,6 +20,7 @@ import com.intellij.ui.treeStructure.SimpleNode; import com.intellij.util.xml.GenericDomValue; import com.intellij.util.xml.DomElement; import com.intellij.ui.SimpleTextAttributes; +import org.jetbrains.annotations.NotNull; public class GenericValueNode extends AbstractDomElementNode { protected GenericDomValue myModelElement; @@ -66,6 +67,7 @@ public class GenericValueNode extends AbstractDomElementNode { return NO_CHILDREN; } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myModelElement}; } diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java index d293ff34118e..8cd06b130a29 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java @@ -108,7 +108,7 @@ public class XmlCompletionContributor extends CompletionContributor { addWordVariants.set(attributeValue.getReferences().length == 0); } - if (addWordVariants.get().booleanValue()) { + if (addWordVariants.get().booleanValue() && parameters.getInvocationCount() > 0) { WordCompletionContributor.addWordCompletionVariants(result, parameters, usedWords); } } diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java index 21c95935dd7a..e7d65657d0b4 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java @@ -57,7 +57,7 @@ public class AddSchemaPrefixIntention extends PsiElementBaseIntentionAction { } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final XmlAttribute xmlns = getXmlnsDeclaration(element); if (xmlns == null) return; final String namespace = xmlns.getValue(); diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java index d524eb2c95bd..34c4809aa811 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java @@ -45,7 +45,7 @@ public class ConvertSchemaPrefixToDefaultIntention extends PsiElementBaseIntenti } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final XmlAttribute xmlns = getXmlnsDeclaration(element); if (xmlns == null) return; SchemaPrefixReference prefixRef = null; diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java index 66c35bb6856d..faa61749ad05 100644 --- a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java +++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java @@ -17,7 +17,6 @@ package com.intellij.codeInspection.htmlInspections; import com.intellij.CommonBundle; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ModifiableModel; @@ -79,7 +78,6 @@ public class AddCustomTagOrAttributeIntentionAction implements LocalQuickFix { final LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)model.getInspectionTool(myInspectionName, element); final HtmlUnknownTagInspection inspection = (HtmlUnknownTagInspection)wrapper.getTool(); inspection.addCustomPropertyName(myName); - model.isProperSetting(HighlightDisplayKey.find(myInspectionName)); try { model.commit(); } diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java index 18ae320ba9d2..9b8d73230b69 100644 --- a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java +++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java @@ -17,7 +17,6 @@ package com.intellij.codeInspection.htmlInspections; import com.intellij.CommonBundle; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.ModifiableModel; @@ -80,7 +79,6 @@ public class AddHtmlTagOrAttributeToCustomsIntention implements IntentionAction final LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)model.getInspectionTool(myInspectionName, file); final XmlEntitiesInspection xmlEntitiesInspection = (XmlEntitiesInspection)wrapper.getTool(); xmlEntitiesInspection.setAdditionalEntries(myType, appendName(xmlEntitiesInspection.getAdditionalEntries(myType))); - model.isProperSetting(HighlightDisplayKey.find(myInspectionName));//update map with non-default settings try { model.commit(); } diff --git a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java index 9c5a4d4ee306..8706f9f0b8a2 100644 --- a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java +++ b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java @@ -55,6 +55,8 @@ public class InternalResourceProvider implements StandardResourceProvider{ impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile10-flat.dtd", "xhtml-mobile/xhtml-mobile10-flat.dtd"); impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile12.dtd", "xhtml-mobile/xhtml-mobile12.dtd"); + impl.addInternalResource("http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd", "xhtml-mobile/xhtml-mobile12.dtd"); + // svg and mathML impl.addIgnoredResource(HtmlUtil.MATH_ML_NAMESPACE); impl.addIgnoredResource(HtmlUtil.SVG_NAMESPACE); diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java index c64803b27d2e..a87b5905ddf5 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java @@ -105,7 +105,8 @@ public class XmlEntityDeclImpl extends XmlElementImpl implements XmlEntityDecl, } public PsiElement parse(PsiFile baseFile, int context, final XmlEntityRef originalElement) { - PsiElement dependsOnElement = getValueElement(baseFile); + PsiElement dep = XmlElement.DEPENDING_ELEMENT.get(getParent()); + PsiElement dependsOnElement = getValueElement(dep instanceof PsiFile ? (PsiFile)dep : baseFile); String value = null; if (dependsOnElement instanceof XmlAttributeValue) { XmlAttributeValue attributeValue = (XmlAttributeValue)dependsOnElement; diff --git a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java index d53f251bd356..9f637d59a193 100644 --- a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java +++ b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java @@ -17,13 +17,11 @@ package com.intellij.xml.util; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.RecursionManager; -import com.intellij.psi.PsiAnchor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.xml.XmlDocument; -import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.xmlb.JDOMXIncluder; @@ -82,12 +80,7 @@ class InclusionProvider implements CachedValueProvider { final XmlTag[] includeTag = extractXpointer(rootTag, xpointer); PsiElement[] result = new PsiElement[includeTag.length]; for (int i = 0; i < includeTag.length; i++) { - XmlTag xmlTag = includeTag[i]; - final PsiElement psiElement = xmlTag.copy(); - psiElement.putUserData(XmlElement.INCLUDING_ELEMENT, xincludeTag.getParentTag()); - psiElement.putUserData(XmlUtil.ORIGINAL_ELEMENT, PsiAnchor.create(xmlTag)); - result[i] = psiElement; - //result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag()); + result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag()); } return result; } diff --git a/xml/impl/src/com/intellij/xml/util/XmlUtil.java b/xml/impl/src/com/intellij/xml/util/XmlUtil.java index 04d5d4d73ed4..da8f6f012152 100644 --- a/xml/impl/src/com/intellij/xml/util/XmlUtil.java +++ b/xml/impl/src/com/intellij/xml/util/XmlUtil.java @@ -55,7 +55,10 @@ import com.intellij.psi.impl.source.xml.XmlEntityRefImpl; import com.intellij.psi.scope.processor.FilterElementProcessor; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.*; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.*; import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; @@ -632,14 +635,7 @@ public class XmlUtil { if (element instanceof XmlEntityRef) { XmlEntityRef ref = (XmlEntityRef)element; - //if ("Number.datatype".equals(ref.getText().substring(1, ref.getTextLength() - 1))) { - // int a = 1; - //} PsiElement newElement = parseEntityRef(targetFile, ref, true); - //if (newElement == null) { - // System.out.println("No image for :" + ref.getText()); - // return true; - //} while (newElement != null) { if (!processElement(newElement, deepFlag, wideFlag, processIncludes)) return false; diff --git a/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java b/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java index 84623dd6d72d..26191bac3220 100644 --- a/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java +++ b/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java @@ -66,7 +66,7 @@ public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool return PsiTreeUtil.getParentOfType(element, XmlTag.class) != null; } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForTag(element, id); } } @@ -88,7 +88,7 @@ public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool return getText(); } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForFile(element, myInspectionId); } diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java index e01543514e80..0f8288f379aa 100644 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java @@ -205,7 +205,7 @@ public abstract class BaseInspection extends XmlSuppressableInspectionTool { return getDisplayName(); } - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { suppress(element.getContainingFile(), getTarget(element)); } diff --git a/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java b/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java index b8631e8083d7..130ea0ef209a 100644 --- a/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java +++ b/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java @@ -24,12 +24,14 @@ import com.intellij.codeInspection.InspectionToolProvider; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection; import com.intellij.javaee.ExternalResourceManagerEx; -import com.intellij.mock.MockProgressIndicator; -import com.intellij.openapi.application.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -48,7 +50,6 @@ import org.intellij.plugins.relaxNG.inspections.RngDomInspection; import org.intellij.plugins.testUtil.IdeaCodeInsightTestCase; import org.intellij.plugins.testUtil.ResourceUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -130,7 +131,7 @@ public abstract class HighlightingTestBase extends UsefulTestCase implements Ide } protected CodeInsightTestFixture createContentFixture(IdeaTestFixtureFactory factory) { - final TestFixtureBuilder builder = factory.createFixtureBuilder(); + final TestFixtureBuilder builder = factory.createFixtureBuilder(getName()); final EmptyModuleFixtureBuilder moduleBuilder = builder.addModule(EmptyModuleFixtureBuilder.class); final IdeaProjectTestFixture fixture = builder.getFixture();