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 extends Iterator>> c = foo();
+ }
+
+ public static Class extends Iterator> 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 super Object> 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 super T> isEmpty() {
+ return null;
+ }
+
+ static class Matcher<T>{}
+
+ class Foo {}
+ void testComment() {
+ Set foos = Collections.emptySet();
+ assertThatComment(foos, hasSize(0));
+ }
+
+ Matcher super Collection extends E>> hasSize(int size) {return size == 0 ? null : null;}
+ void assertThatComment(T actual, Matcher super T> 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 extends JavaFileObject> 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 extends GotoRelatedItem> 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 super Psi> 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