Merge remote branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2012-03-29 18:30:57 +04:00
290 changed files with 3920 additions and 2258 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
<element id="module-output" name="javac2" />
<element id="module-output" name="forms-compiler" />
<element id="module-output" name="forms_rt" />
<element id="module-output" name="notNull" />
<element id="module-output" name="instrumentation-util" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jna-utils.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jna.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jdom.jar" path-in-jar="/" />
+1 -1
View File
@@ -51,6 +51,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/icons/icons.iml" filepath="$PROJECT_DIR$/platform/icons/icons.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/java/idea-ui/idea-ui.iml" filepath="$PROJECT_DIR$/java/idea-ui/idea-ui.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/images/images.iml" filepath="$PROJECT_DIR$/images/images.iml" />
<module fileurl="file://$PROJECT_DIR$/java/compiler/instrumentation-util/instrumentation-util.iml" filepath="$PROJECT_DIR$/java/compiler/instrumentation-util/instrumentation-util.iml" group="java/compiler" />
<module fileurl="file://$PROJECT_DIR$/plugins/java-i18n/java-i18n.iml" filepath="$PROJECT_DIR$/plugins/java-i18n/java-i18n.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/java/java-impl/java-impl.iml" filepath="$PROJECT_DIR$/java/java-impl/java-impl.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/java-psi-api/java-psi-api.iml" filepath="$PROJECT_DIR$/java/java-psi-api/java-psi-api.iml" group="java" />
@@ -80,7 +81,6 @@
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" filepath="$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/java/compiler/notNull/notNull.iml" filepath="$PROJECT_DIR$/java/compiler/notNull/notNull.iml" group="java/compiler" />
<module fileurl="file://$PROJECT_DIR$/java/openapi/openapi.iml" filepath="$PROJECT_DIR$/java/openapi/openapi.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-api/platform-api.iml" filepath="$PROJECT_DIR$/platform/platform-api/platform-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" filepath="$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" group="platform" />
@@ -43,7 +43,7 @@ public abstract class BaseParseTestcase extends UsefulTestCase{
protected void setUp() throws Exception {
super.setUp();
final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
final TestFixtureBuilder<IdeaProjectTestFixture> builder = fixtureFactory.createFixtureBuilder();
final TestFixtureBuilder<IdeaProjectTestFixture> builder = fixtureFactory.createFixtureBuilder(getName());
myFixture = fixtureFactory.createCodeInsightFixture(builder.getFixture());
myFixture.setTestDataPath(getTestDataPath());
+2 -2
View File
@@ -77,7 +77,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
//noinspection GroovyAssignabilityCheck
List<String> 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") {
+1 -1
View File
@@ -31,7 +31,7 @@
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="lvcs-api" />
<orderEntry type="module" module-name="lvcs-impl" />
<orderEntry type="module" module-name="notNull" />
<orderEntry type="module" module-name="instrumentation-util" />
<orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="module" module-name="platform-impl" />
@@ -13,6 +13,7 @@
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="library" scope="TEST" name="JUnit3" level="project" />
<orderEntry type="library" name="jgoodies-forms" level="project" />
<orderEntry type="module" module-name="instrumentation-util" exported="" />
</component>
</module>
@@ -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<groups.length; groupIndex++) {
String[] ids = groups [groupIndex].getComponentIds();
try {
InstrumentationClassFinder.PseudoClass buttonGroupClass = null; // cached
int groupLocal = generator.newLocal(ourButtonGroupType);
for(int groupIndex=0; groupIndex<groups.length; groupIndex++) {
String[] ids = groups [groupIndex].getComponentIds();
if (ids.length > 0) {
generator.newInstance(ourButtonGroupType);
generator.dup();
generator.invokeConstructor(ourButtonGroupType, Method.getMethod("void <init>()"));
generator.storeLocal(groupLocal);
if (ids.length > 0) {
generator.newInstance(ourButtonGroupType);
generator.dup();
generator.invokeConstructor(ourButtonGroupType, Method.getMethod("void <init>()"));
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<ids.length; i++) {
Integer localInt = (Integer) myIdToLocalMap.get(ids [i]);
if (localInt != null) {
if (groups [groupIndex].isBound() && !myIgnoreCustomCreation) {
if (buttonGroupClass == null) {
buttonGroupClass = myFinder.loadClass(ButtonGroup.class.getName());
}
validateFieldClass(groups [groupIndex].getName(), buttonGroupClass, null);
generator.loadThis();
generator.loadLocal(groupLocal);
generator.loadLocal(localInt.intValue());
generator.invokeVirtual(ourButtonGroupType, Method.getMethod("void add(javax.swing.AbstractButton)"));
generator.putField(getMainClassType(), groups [groupIndex].getName(), ourButtonGroupType);
}
for(int i = 0; i<ids.length; i++) {
Integer localInt = (Integer) myIdToLocalMap.get(ids [i]);
if (localInt != null) {
generator.loadLocal(groupLocal);
generator.loadLocal(localInt.intValue());
generator.invokeVirtual(ourButtonGroupType, Method.getMethod("void add(javax.swing.AbstractButton)"));
}
}
}
}
}
catch (IOException e) {
throw new CodeGenerationException(rootContainer.getId(), e.getMessage(), e);
}
catch (ClassNotFoundException e) {
throw new CodeGenerationException(rootContainer.getId(), e.getMessage(), e);
}
}
}
@@ -756,14 +784,14 @@ public class AsmCodeGenerator {
return Type.getType("L" + myClassName + ";");
}
private void validateFieldBinding(LwComponent component, final Class componentClass) throws CodeGenerationException {
private void validateFieldBinding(LwComponent component, final InstrumentationClassFinder.PseudoClass componentClass) throws CodeGenerationException {
String binding = component.getBinding();
if (binding == null) return;
validateFieldClass(binding, componentClass, component.getId());
}
private void validateFieldClass(String binding, Class componentClass, String componentId) throws CodeGenerationException {
private void validateFieldClass(String binding, InstrumentationClassFinder.PseudoClass componentClass, String componentId) throws CodeGenerationException {
if (!myFieldDescMap.containsKey(binding)) {
throw new CodeGenerationException(componentId, "Cannot bind: field does not exist: " + myClassToBind + "." + binding);
}
@@ -773,15 +801,17 @@ public class AsmCodeGenerator {
throw new CodeGenerationException(componentId, "Cannot bind: field is of primitive type: " + myClassToBind + "." + binding);
}
Class fieldClass;
try {
fieldClass = myLoader.loadClass(fieldType.getClassName());
final InstrumentationClassFinder.PseudoClass fieldClass = myFinder.loadClass(fieldType.getClassName());
if (!fieldClass.isAssignableFrom(componentClass)) {
throw new CodeGenerationException(componentId, "Cannot bind: Incompatible types. Cannot assign " + componentClass.getName().replace('/', '.') + " to field " + myClassToBind + "." + binding);
}
}
catch (ClassNotFoundException e) {
throw new CodeGenerationException(componentId, "Class not found: " + fieldType.getClassName());
}
if (!fieldClass.isAssignableFrom(componentClass)) {
throw new CodeGenerationException(componentId, "Cannot bind: Incompatible types. Cannot assign " + componentClass.getName() + " to field " + myClassToBind + "." + binding);
catch (IOException e) {
throw new CodeGenerationException(componentId, e.getMessage(), e);
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.uiDesigner.compiler;
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
import com.intellij.uiDesigner.lw.FontDescriptor;
import com.intellij.uiDesigner.lw.LwComponent;
import com.intellij.uiDesigner.lw.LwIntrospectedProperty;
@@ -41,7 +42,7 @@ public class FontPropertyCodeGenerator extends PropertyCodeGenerator {
private static final Method ourGetStyleMethod = new Method("getStyle", Type.INT_TYPE, new Type[0] );
public boolean generateCustomSetValue(final LwComponent lwComponent,
final Class componentClass,
final InstrumentationClassFinder.PseudoClass componentClass,
final LwIntrospectedProperty property,
final GeneratorAdapter generator,
final int componentLocal, final String formClassName) {
@@ -15,10 +15,13 @@
*/
package com.intellij.uiDesigner.compiler;
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
import com.intellij.uiDesigner.lw.LwComponent;
import com.intellij.uiDesigner.lw.LwIntrospectedProperty;
import org.objectweb.asm.commons.GeneratorAdapter;
import java.io.IOException;
/**
* @author yole
*/
@@ -26,13 +29,13 @@ public abstract class PropertyCodeGenerator {
public abstract void generatePushValue(final GeneratorAdapter generator, final Object value);
public boolean generateCustomSetValue(final LwComponent lwComponent,
final Class componentClass, final LwIntrospectedProperty property,
final InstrumentationClassFinder.PseudoClass componentClass, final LwIntrospectedProperty property,
final GeneratorAdapter generator,
final int componentLocal, final String formClassName) {
final int componentLocal, final String formClassName) throws IOException, ClassNotFoundException {
return false;
}
public void generateClassStart(AsmCodeGenerator.FormClassVisitor visitor, final String name, final ClassLoader loader) {
public void generateClassStart(AsmCodeGenerator.FormClassVisitor visitor, final String name, final InstrumentationClassFinder classFinder) {
}
public void generateClassEnd(AsmCodeGenerator.FormClassVisitor visitor) {
@@ -15,6 +15,7 @@
*/
package com.intellij.uiDesigner.compiler;
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
import com.intellij.uiDesigner.core.SupportCode;
import com.intellij.uiDesigner.lw.LwComponent;
import com.intellij.uiDesigner.lw.LwIntrospectedProperty;
@@ -27,9 +28,10 @@ import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import javax.swing.*;
import java.io.IOException;
import java.util.HashSet;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.HashSet;
/**
* @author yole
@@ -47,12 +49,12 @@ public class StringPropertyCodeGenerator extends PropertyCodeGenerator implement
private final Set myClassesRequiringLoadButtonText = new HashSet();
private boolean myHaveSetDisplayedMnemonicIndex = false;
public void generateClassStart(AsmCodeGenerator.FormClassVisitor visitor, final String name, final ClassLoader loader) {
public void generateClassStart(AsmCodeGenerator.FormClassVisitor visitor, final String name, final InstrumentationClassFinder classFinder) {
myClassesRequiringLoadLabelText.remove(name);
myClassesRequiringLoadButtonText.remove(name);
try {
Class c = loader.loadClass(AbstractButton.class.getName());
if (c.getMethod("getDisplayedMnemonicIndex", new Class[0]) != null) {
InstrumentationClassFinder.PseudoClass pseudo = classFinder.loadClass(AbstractButton.class.getName());
if (!pseudo.findMethods("getDisplayedMnemonicIndex").isEmpty()) {
myHaveSetDisplayedMnemonicIndex = true;
}
}
@@ -62,25 +64,27 @@ public class StringPropertyCodeGenerator extends PropertyCodeGenerator implement
}
public boolean generateCustomSetValue(final LwComponent lwComponent,
final Class componentClass,
final InstrumentationClassFinder.PseudoClass componentClass,
final LwIntrospectedProperty property,
final GeneratorAdapter generator,
final int componentLocal,
final String formClassName) {
final String formClassName) throws IOException, ClassNotFoundException {
final InstrumentationClassFinder.PseudoClass abstractButtonClass = componentClass.getFinder().loadClass(AbstractButton.class.getName());
final InstrumentationClassFinder.PseudoClass jLabelClass = componentClass.getFinder().loadClass(JLabel.class.getName());
if ("text".equals(property.getName()) &&
(AbstractButton.class.isAssignableFrom(componentClass) || JLabel.class.isAssignableFrom(componentClass))) {
(abstractButtonClass.isAssignableFrom(componentClass) || jLabelClass.isAssignableFrom(componentClass))) {
final StringDescriptor propertyValue = (StringDescriptor)lwComponent.getPropertyValue(property);
if (propertyValue.getValue() != null) {
final SupportCode.TextWithMnemonic textWithMnemonic = SupportCode.parseText(propertyValue.getValue());
if (textWithMnemonic.myMnemonicIndex >= 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;
}
@@ -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 <code>null</code> if
* no errors were detected.
*/
/**
* Validates that specified class represents {@link javax.swing.JComponent} with
* empty constructor.
*
* @return descriptive human readable error message or <code>null</code> 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;
}
}
+1 -1
View File
@@ -14,7 +14,7 @@
<orderEntry type="module" module-name="openapi" />
<orderEntry type="library" name="Trove4j" level="project" />
<orderEntry type="module" module-name="java-runtime" />
<orderEntry type="module" module-name="notNull" />
<orderEntry type="module" module-name="instrumentation-util" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="library" name="Eclipse" level="project" />
<orderEntry type="module" module-name="platform-api" />
@@ -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);
@@ -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) {
@@ -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<String, PseudoClass> myLoaded = new HashMap<String, PseudoClass>(); // 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<PseudoMethod> 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<PseudoMethod> 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<PseudoMethod> getMethods() {
return myMethods;
}
public List<PseudoMethod> findMethods(String name) {
final List<PseudoMethod> result = new ArrayList<PseudoMethod>();
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 ("<init>".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<PseudoMethod> myMethods = new ArrayList<PseudoMethod>();
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();
}
}
@@ -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);
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@
<orderEntry type="module" module-name="forms-compiler" />
<orderEntry type="module" module-name="forms_rt" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="module" module-name="notNull" />
<orderEntry type="module" module-name="instrumentation-util" />
</component>
<component name="copyright">
<Base>
@@ -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());
}
}
}
@@ -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);
@@ -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);
}
}
@@ -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<interfaces.length; i++) {
myInterfaces[i] = interfaces[i].getName().replace('.', '/');
}
isInterface = repr.isInterface();
}
private PseudoClass(final String name, final String superClass, final String[] interfaces, final boolean anInterface) {
myName = name;
mySuperClass = superClass;
myInterfaces = interfaces;
isInterface = anInterface;
}
private PseudoClass getSuperClass() throws IOException, ClassNotFoundException {
if (mySuperClass == null) {
return null;
}
return loadClass(mySuperClass);
}
private PseudoClass[] getInterfaces() throws IOException, ClassNotFoundException {
if (myInterfaces == null) {
return new PseudoClass[0];
}
final PseudoClass[] result = new PseudoClass[myInterfaces.length];
for (int i = 0; i < result.length; i++) {
result[i] = loadClass(myInterfaces[i]);
}
return result;
}
public boolean equals (final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return myName.equals(((PseudoClass)o).myName);
}
private boolean isSubclassOf(final PseudoClass x) throws IOException, ClassNotFoundException {
for (PseudoClass c = this; c != null; c = c.getSuperClass()) {
final PseudoClass superClass = c.getSuperClass();
if (superClass != null && superClass.equals(x)) {
return true;
}
}
return false;
}
private boolean implementsInterface(final PseudoClass x) throws IOException, ClassNotFoundException {
for (PseudoClass c = this; c != null; c = c.getSuperClass()) {
final PseudoClass[] tis = c.getInterfaces();
for (int i = 0; i < tis.length; ++i) {
final PseudoClass ti = tis[i];
if (ti.equals(x) || ti.implementsInterface(x)) {
return true;
}
}
}
return false;
}
private boolean isAssignableFrom(final PseudoClass x) throws IOException, ClassNotFoundException {
if (this.equals(x)) {
return true;
}
if (x.isSubclassOf(this)) {
return true;
}
if (x.implementsInterface(this)) {
return true;
}
if (x.isInterface && myName.equals("java/lang/Object")) {
return true;
}
return false;
}
public String getCommonSuperClassName(final PseudoClass x) throws IOException, ClassNotFoundException {
if (isAssignableFrom(x)) {
return myName;
}
if (x.isAssignableFrom(this)) {
return x.myName;
}
if (isInterface || x.isInterface) {
return "java/lang/Object";
}
else {
PseudoClass c = this;
do {
c = c.getSuperClass();
}
while (!c.isAssignableFrom(x));
return c.myName;
}
}
}
final MemoryClassLoader myLoader;
public PseudoClassLoader(final URL[] classpath) {
final URLClassLoader classpathLoader = new URLClassLoader(classpath, null);
myLoader = new MemoryClassLoader(classpathLoader);
}
public ClassLoader getLoader () {
return myLoader;
}
public void defineClass (final String internalName, final byte[] data) {
myDefinedClasses.put(internalName, createPseudoClass(new ClassReader(data)));
myDefinedClassesData.put(internalName.replace('/', '.'), data);
}
private static class V extends EmptyVisitor {
public String superName = null;
public String[] interfaces = null;
public String name = null;
public boolean isInterface = false;
public void visitAttribute(Attribute attr) {
super.visitAttribute(attr);
}
public void visit(int version, int access, String pName, String signature, String pSuperName, String[] pInterfaces) {
superName = pSuperName;
interfaces = pInterfaces;
name = pName;
isInterface = (access & Opcodes.ACC_INTERFACE) > 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;
}
}
@@ -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<ReferenceType, byte[]> redefineMap = new HashMap<ReferenceType,byte[]>();
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<ReferenceType> 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<ReferenceType, byte[]> myRedefineMap = new HashMap<ReferenceType, byte[]>();
private int myProcessedClassesCount;
private int myPartiallyRedefinedClassesCount;
public RedefineProcessor(VirtualMachineProxyImpl virtualMachineProxy) {
myVirtualMachineProxy = virtualMachineProxy;
}
public void processClass(String qualifiedName, byte[] content) throws Throwable {
final List<ReferenceType> 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;
}
}
}
@@ -80,6 +80,7 @@ public class PackagingElementNode<E extends PackagingElement<?>> extends Artifac
return myPackagingElements.size() == 1 ? myPackagingElements.get(0) : null;
}
@NotNull
@Override
public Object[] getEqualityObjects() {
return ArrayUtil.toObjectArray(myPackagingElements);
@@ -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};
@@ -35,6 +35,7 @@ public class SourceItemsTreeRoot extends SourceItemNodeBase {
return null;
}
@NotNull
@Override
public Object[] getEqualityObjects() {
return new Object[]{"root"};
@@ -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) {
@@ -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;
@@ -269,6 +269,7 @@ public abstract class ChooseLibrariesDialogBase extends DialogWrapper {
return 0;
}
@NotNull
@Override
public Object[] getEqualityObjects() {
return new Object[] {myElement};
@@ -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;
@@ -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;
@@ -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;
@@ -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();
@@ -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);
@@ -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;
}
@@ -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));
}
@@ -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();
@@ -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;
@@ -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;
@@ -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
@@ -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);
@@ -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);
}
}
@@ -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;
}
@@ -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);
}
@@ -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),
@@ -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<PsiClass>() {
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;
}
}
);
@@ -144,6 +144,7 @@ public class SliceNode extends AbstractTreeNode<SliceUsage> implements Duplicate
@Override
protected PresentationData createPresentation() {
return new PresentationData(){
@NotNull
@Override
public Object[] getEqualityObjects() {
return ArrayUtil.append(super.getEqualityObjects(), changed);
@@ -70,4 +70,5 @@ public enum JavaSdkVersion {
String.format("Can't map Java SDK by description (%s). Available values: %s", description, Arrays.toString(values()))
);
}
}
@@ -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());
}
}
@@ -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();
@@ -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) {
@@ -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) {
@@ -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;
}
}
}
@@ -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;
+1 -1
View File
@@ -17,7 +17,7 @@
<orderEntry type="module" module-name="java-i18n" />
<orderEntry type="module" module-name="compiler-impl" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="module" module-name="notNull" />
<orderEntry type="module" module-name="instrumentation-util" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="module" module-name="IntelliLang-java" scope="RUNTIME" />
<orderEntry type="module" module-name="IntelliLang-xml" scope="RUNTIME" />
@@ -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() {
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends java.util.Iterator>>', required: 'java.lang.Class<? extends java.util.Iterator<?>>'">Class<? extends Iterator<?>> c = foo();</error>
}
public static Class<? extends Iterator> foo() {
return null;
}
}
@@ -7,7 +7,7 @@ interface Matcher<T> {
}
interface ArgumentConstraintPhrases {
<T> T with(Matcher<T> matcher);
<error descr="'with(Matcher<T>)' clashes with 'with(Matcher<Boolean>)'; both methods have same erasure"><T> T with(Matcher<T> matcher)</error>;
boolean with(Matcher<Boolean> matcher);
byte with(Matcher<Byte> matcher);
short with(Matcher<Short> matcher);
@@ -19,7 +19,7 @@ interface ArgumentConstraintPhrases {
class ExpectationGroupBuilder implements ArgumentConstraintPhrases {
public <T> T with(final Matcher<T> matcher) {
<error descr="'with(Matcher<T>)' clashes with 'with(Matcher<Boolean>)'; both methods have same erasure">public <T> T with(final Matcher<T> matcher)</error> {
return null;
}
@@ -0,0 +1,48 @@
/** @noinspection UnusedDeclaration*/
interface Matcher<T> {
boolean matches(Object object);
void _dont_implement_Matcher___instead_extend_BaseMatcher_();
}
interface ArgumentConstraintPhrases {
<T> T with(Matcher<T> matcher);
boolean with(Matcher<Boolean> matcher);
byte with(Matcher<Byte> matcher);
int with(Matcher<Integer> matcher);
long with(Matcher<Long> matcher);
float with(Matcher<Float> matcher);
double with(Matcher<Double> matcher);
}
class ExpectationGroupBuilder implements ArgumentConstraintPhrases {
public <T> T with(final Matcher<T> matcher) {
return null;
}
public boolean with(final Matcher<Boolean> matcher) {
return false;
}
public byte with(final Matcher<Byte> matcher) {
return 0;
}
public int with(final Matcher<Integer> matcher) {
return 0;
}
public long with(final Matcher<Long> matcher) {
return 0;
}
public float with(final Matcher<Float> matcher) {
return 0;
}
public double with(final Matcher<Double> matcher) {
return 0;
}
}
@@ -0,0 +1,9 @@
class A {
private int value = 1;
static class B<T extends A> {
void print(T t) {
System.out.println(t.<error descr="'value' has private access in 'A'">value</error>);
}
}
}
@@ -0,0 +1,9 @@
class A {
private int value = 1;
static class B<T extends A> {
void print(T t) {
System.out.println(t.value);
}
}
}
@@ -172,4 +172,48 @@ class My<T> {
public void test() {
if (getSuperclass() == List.class);
}
}
class IDEA75178 {
void test(Set<String> labels) {
final Matcher<? super Object> empty = isEmpty();
assertThat(labels, empty);
assertAlsoThat(empty, labels);
}
public static <T> void assertThat(T actual, Matcher<T> matcher) { throw new AssertionError(actual.toString() + matcher.toString());}
public static <T> void assertAlsoThat(Matcher<T> matcher, T actual) { throw new AssertionError(actual.toString() + matcher.toString());}
public static <T> Matcher<? super T> isEmpty() {
return null;
}
static class Matcher<<warning descr="Type parameter 'T' is never used">T</warning>>{}
class Foo {}
void testComment() {
Set<Foo> foos = Collections.emptySet();
assertThatComment(foos, hasSize(0));
}
<E> Matcher<? super Collection<? extends E>> hasSize(int size) {return size == 0 ? null : null;}
<T> void assertThatComment(T actual, Matcher<? super T> matcher){ throw new AssertionError(actual.toString() + matcher.toString());}
}
class IDEA66750 {
public void test() {
List<List<String>> data = new ArrayList<List<String>>();
List<List<?>> y = <error descr="Inconvertible types; cannot cast 'java.util.List<java.util.List<java.lang.String>>' to 'java.util.List<java.util.List<?>>'">(List<List<?>>)data</error>;
System.out.println(y);
ArrayList<Number> al = <error descr="Inconvertible types; cannot cast 'java.util.ArrayList<java.lang.Integer>' to 'java.util.ArrayList<java.lang.Number>'">(ArrayList<Number>) new ArrayList<Integer>(1)</error>;
System.out.println(al);
}
}
class IDEA73377 {
public Iterator<Map.Entry<Map.Entry<?, ?>, ?>> iterator(Map<?, ?> map) {
//noinspection unchecked
return <error descr="Inconvertible types; cannot cast 'java.util.Iterator<java.util.Map.Entry<capture<?>,capture<?>>>' to 'java.util.Iterator<java.util.Map.Entry<java.util.Map.Entry<?,?>,?>>'">(Iterator<Map.Entry<Map.Entry<?, ?>, ?>>)map.entrySet().iterator()</error>;
}
}
@@ -0,0 +1,6 @@
// "Iterate" "false"
class Test {
void foo() {
final Annotation[] annotations = getClass().getAnnotat<caret>ions();
}
}
@@ -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(){}
}
}
}
@@ -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 {
@Overr<caret>ide
void foo(){}
}
}
}
@@ -3,7 +3,7 @@
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA jdk" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="masterDetails">
@@ -0,0 +1,3 @@
public class ModuleSourceAsLibrarySource {
<ref>ModuleSourceAsLibrarySourceDep field;
}
@@ -0,0 +1 @@
public class ModuleSourceAsLibrarySourceDep {}
@@ -37,7 +37,7 @@ public class SuppressExternalTest extends UsefulTestCase {
public void setUp() throws Exception {
super.setUp();
final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
final TestFixtureBuilder<IdeaProjectTestFixture> testFixtureBuilder = fixtureFactory.createFixtureBuilder();
final TestFixtureBuilder<IdeaProjectTestFixture> testFixtureBuilder = fixtureFactory.createFixtureBuilder(getName());
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture());
myFixture.setTestDataPath(PathManagerEx.getTestDataPath() + "/codeInsight/externalAnnotations");
final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class);
@@ -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()));
@@ -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");
@@ -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
<caret>
'''
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 = '''\
<selection> line1
line2</selection>\
</selection><caret>\
'''
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 = '''\
<selection> line1</selection><caret>\
'''
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<caret>
@@ -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() {
<caret>
}
}
'''
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)
}
}
@@ -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(<caret>);
}
};
}
}
"""
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 {
@@ -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<InspectionToolWrapper> list = new ArrayList<InspectionToolWrapper>();
list.add(createTool("foo"));
InspectionToolRegistrar registrar = new InspectionToolRegistrar(null) {
@Override
public List<InspectionToolWrapper> createTools() {
LocalInspectionEP foo = new LocalInspectionEP();
foo.shortName = "foo";
return list;
}
};
InspectionProfileImpl profile = new InspectionProfileImpl("Foo", registrar, InspectionProfileManager.getInstance());
profile.setBaseProfile(null);
List<ScopeToolState> 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<Tools>(), new ArrayList<Tools>(), new ArrayList<Tools>());
Map<String,Tools> 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);
}
}
@@ -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();
@@ -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)
}
}
@@ -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;
}
}
@@ -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();
}
+1 -1
View File
@@ -12,7 +12,7 @@
<orderEntry type="module" module-name="util" exported="" />
<orderEntry type="module" module-name="forms_rt" />
<orderEntry type="module" module-name="forms-compiler" />
<orderEntry type="module" module-name="notNull" />
<orderEntry type="module" module-name="instrumentation-util" />
<orderEntry type="library" exported="" name="asm" level="project" />
<orderEntry type="library" name="JDOM" level="project" />
<orderEntry type="library" name="NanoXML" level="project" />
@@ -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";
}
@@ -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);
}
};
}
@@ -34,7 +34,7 @@ public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
private final AtomicReference<State> myState = new AtomicReference<State>(State.DISCONNECTED);
protected final ChannelPipelineFactory myPipelineFactory;
protected final ChannelFactory myChannelFactory;
protected ChannelFuture myConnectFuture;
protected volatile ChannelFuture myConnectFuture;
private final ProtobufClientMessageHandler<T> myMessageHandler;
public SimpleProtobufClient(final MessageLite msgDefaultInstance, final AsyncTaskExecutor asyncExec, final UUIDGetter uuidGetter) {
@@ -146,8 +146,9 @@ public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
public final RequestFuture<T> sendMessage(final UUID messageId, MessageLite message, @Nullable final T responseHandler, @Nullable final RequestFuture.CancelAction<T> cancelAction) {
final RequestFuture<T> requestFuture = new RequestFuture<T>(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()) {
@@ -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();
}
}
@@ -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<Future> myAsyncTasks = new ArrayList<Future>();
public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map<String, String> 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<File> outputPaths = new LinkedHashSet<File>();
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 {
@@ -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;
@@ -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<File> files, Collection<File> 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<File> sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.<File>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<File, String> 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<File, String> 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<File> platformCp,
Collection<File> classpath,
final OutputFilesSink outputSink) throws MalformedURLException {
Map<File, String> 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<URL> urls = new ArrayList<URL>(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<File> platformCp, Collection<File> classpath,
Map<File, String> chunkSourcePath,
OutputFilesSink outputSink) throws MalformedURLException {
final List<URL> urls = new ArrayList<URL>();
for (Collection<File> 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<List<String>> JAVAC_OPTIONS = Key.create("_javac_options_");
private static final Key<List<String>> 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<File, String> chunkSourcePath,
final ClassLoader loader,
final InstrumentationClassFinder finder, Collection<File> 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<File, String> mySourceRoots;
private final Collection<File> 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;
@@ -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<Boolean> doneSomething = new Ref<Boolean>(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);
@@ -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<JavacServerResponseHandler>{
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();
+1
View File
@@ -34,6 +34,7 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module" module-name="instrumentation-util" />
</component>
</module>
@@ -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<File> sourceFiles
List<String> sourceRoots
@@ -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<File> formFiles = new ArrayList<File>();
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();
}
}
}
@@ -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()]);
}
}
@@ -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<File, Archive> myArchives;
private final Map<File, Boolean> myIsFile = new ConcurrentHashMap<File, Boolean>();
private Callbacks.Backend callback;
private PseudoClassLoader loader;
private InstrumentationClassFinder classFinder;
private Map<String, byte[]> myCompiledClasses = new HashMap<String, byte[]>();
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();
}
}
}
@@ -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 <code>first</code>)
* @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 <code>first</code>)
* @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 <code>first</code> 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 <code>first</code>)
* @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 <code>first</code>)
* @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 <code>first</code> 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.
*
* <p/>
* 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> T getCopyableUserData(Key<T> key);
@Nullable
<T> T getCopyableUserData(Key<T> 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 <code>getParent()</code>,
* 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);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Some files were not shown because too many files have changed in this diff Show More