mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 09:03:31 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -16,5 +16,6 @@
|
||||
<orderEntry type="module" module-name="platform-resources-en" exported="" />
|
||||
<orderEntry type="library" name="automaton" level="project" />
|
||||
<orderEntry type="library" name="CGLIB" level="project" />
|
||||
<orderEntry type="library" name="ASM" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import net.sf.cglib.asm.$ClassVisitor;
|
||||
import net.sf.cglib.asm.$Label;
|
||||
import net.sf.cglib.asm.$Type;
|
||||
import net.sf.cglib.core.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.org.objectweb.asm.ClassWriter;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
@@ -33,13 +32,6 @@ public class InstanceofCheckerGenerator {
|
||||
private static final InstanceofCheckerGenerator ourInstance;
|
||||
|
||||
static {
|
||||
try {
|
||||
ClassGenerator.class.getDeclaredMethod("generateClass", $ClassVisitor.class);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException("Incorrect cglib version in the classpath, source=" + PathManager.getJarPathForClass(ClassGenerator.class));
|
||||
}
|
||||
|
||||
try {
|
||||
ourInstance = new InstanceofCheckerGenerator();
|
||||
}
|
||||
@@ -52,6 +44,7 @@ public class InstanceofCheckerGenerator {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
private final ConcurrentFactoryMap<Class, Condition<Object>> myCache = new ConcurrentFactoryMap<Class, Condition<Object>>() {
|
||||
@Override
|
||||
protected Condition<Object> create(final Class key) {
|
||||
@@ -64,76 +57,73 @@ public class InstanceofCheckerGenerator {
|
||||
};
|
||||
}
|
||||
|
||||
return new InstanceofClassGenerator(key).createClass();
|
||||
String name = "com.intellij.util.InstanceofChecker$$$$$" + key.getName().replace('.', '$');
|
||||
//noinspection unchecked
|
||||
return (Condition<Object>)ReflectionUtil.newInstance(obtainClass(key, name, generateConditionClass(key, name)));
|
||||
}
|
||||
};
|
||||
|
||||
private synchronized Class obtainClass(Class checkedClass, String name, byte[] bytes) {
|
||||
ClassLoader loader = checkedClass.getClassLoader();
|
||||
if (loader == null) loader = InstanceofCheckerGenerator.class.getClassLoader();
|
||||
try {
|
||||
return loader.loadClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException ignore) {
|
||||
}
|
||||
|
||||
try {
|
||||
return ReflectionUtil.defineClass(name, bytes, loader);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Condition<Object> getInstanceofChecker(final Class<?> someClass) {
|
||||
return myCache.get(someClass);
|
||||
}
|
||||
|
||||
private static String toInternalName(Class<?> someClass) {
|
||||
return someClass.getName().replace('.', '/');
|
||||
return toInternalName(someClass.getName());
|
||||
}
|
||||
|
||||
private static class InstanceofClassGenerator extends AbstractClassGenerator {
|
||||
private static final Source SOURCE = new Source("IntellijInstanceof");
|
||||
private final Class<?> myCheckedClass;
|
||||
|
||||
public InstanceofClassGenerator(Class<?> checkedClass) {
|
||||
super(SOURCE);
|
||||
myCheckedClass = checkedClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassLoader getDefaultClassLoader() {
|
||||
return myCheckedClass.getClassLoader();
|
||||
}
|
||||
|
||||
public Condition<Object> createClass() {
|
||||
return (Condition<Object>)super.create(myCheckedClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object firstInstance(Class type) throws Exception {
|
||||
return type.newInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object nextInstance(Object instance) throws Exception {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateClass($ClassVisitor classVisitor) throws Exception {
|
||||
ClassEmitter cv = new ClassEmitter(classVisitor);
|
||||
|
||||
cv.visit(Constants.V1_2, Modifier.PUBLIC, "com/intellij/util/InstanceofChecker$$$$$" + myCheckedClass.getName().replace('.', '$'), null, toInternalName(Object.class), new String[]{toInternalName(Condition.class)});
|
||||
cv.visitSource(Constants.SOURCE_FILE, null);
|
||||
final Signature signature = new Signature("<init>", "()V");
|
||||
final CodeEmitter cons = cv.begin_method(Modifier.PUBLIC, signature, new $Type[0]);
|
||||
cons.load_this();
|
||||
cons.dup();
|
||||
cons.super_invoke_constructor(signature);
|
||||
cons.return_value();
|
||||
cons.end_method();
|
||||
|
||||
final CodeEmitter e = cv.begin_method(Modifier.PUBLIC, new Signature("value", "(L" + toInternalName(Object.class) + ";)Z"), new $Type[0]);
|
||||
e.load_arg(0);
|
||||
e.instance_of($Type.getType(myCheckedClass));
|
||||
|
||||
$Label fail = e.make_label();
|
||||
e.if_jump(CodeEmitter.EQ, fail);
|
||||
e.push(true);
|
||||
e.return_value();
|
||||
|
||||
e.mark(fail);
|
||||
e.push(false);
|
||||
e.return_value();
|
||||
e.end_method();
|
||||
|
||||
cv.visitEnd();
|
||||
}
|
||||
@NotNull
|
||||
private static String toInternalName(String name) {
|
||||
return name.replace('.', '/');
|
||||
}
|
||||
|
||||
private static byte[] generateConditionClass(Class<?> checkedClass, final String generatedName) {
|
||||
ClassWriter cv = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
cv.visit(Opcodes.V1_2, Modifier.PUBLIC, toInternalName(generatedName), null, toInternalName(Object.class), new String[]{toInternalName(Condition.class)});
|
||||
|
||||
defaultConstructor(cv);
|
||||
|
||||
conditionValue(checkedClass, cv);
|
||||
|
||||
cv.visitEnd();
|
||||
return cv.toByteArray();
|
||||
}
|
||||
|
||||
private static void defaultConstructor(ClassWriter cv) {
|
||||
MethodVisitor mv = cv.visitMethod(Modifier.PUBLIC, "<init>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, toInternalName(Object.class), "<init>", "()V", false);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private static void conditionValue(Class<?> checkedClass, ClassWriter cv) {
|
||||
MethodVisitor mv = cv.visitMethod(Modifier.PUBLIC, "value", "(L" + toInternalName(Object.class) + ";)Z", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitTypeInsn(Opcodes.INSTANCEOF, Type.getType(checkedClass).getInternalName());
|
||||
mv.visitInsn(Opcodes.IRETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -292,8 +292,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
public void commitDocument(@NotNull final Document doc) {
|
||||
final Document document = doc instanceof DocumentWindow ? ((DocumentWindow)doc).getDelegate() : doc;
|
||||
|
||||
VirtualFile vFile = getVirtualFile(document);
|
||||
if (vFile != null && !isFreeThreaded(vFile)) {
|
||||
if (isEventSystemEnabled(document)) {
|
||||
((TransactionGuardImpl)TransactionGuard.getInstance()).assertWriteActionAllowed();
|
||||
}
|
||||
|
||||
@@ -302,6 +301,14 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEventSystemEnabled(Document document) {
|
||||
VirtualFile vFile = getVirtualFile(document);
|
||||
if (vFile == null || isFreeThreaded(vFile)) return false;
|
||||
|
||||
FileViewProvider viewProvider = getCachedViewProvider(document);
|
||||
return viewProvider != null && viewProvider.isEventSystemEnabled();
|
||||
}
|
||||
|
||||
// public for Upsource
|
||||
public boolean finishCommit(@NotNull final Document document,
|
||||
@NotNull final List<Processor<Document>> finishProcessors,
|
||||
|
||||
@@ -435,9 +435,9 @@ public abstract class ChooseByNameBase {
|
||||
group.add(new ShowFindUsagesAction() {
|
||||
@Override
|
||||
public PsiElement[][] getElements() {
|
||||
final Object[] objects = myListModel.toArray();
|
||||
final List<PsiElement> prefixMatchElements = new ArrayList<>(objects.length);
|
||||
final List<PsiElement> nonPrefixMatchElements = new ArrayList<>(objects.length);
|
||||
final List<Object> objects = myListModel.getItems();
|
||||
final List<PsiElement> prefixMatchElements = new ArrayList<>(objects.size());
|
||||
final List<PsiElement> nonPrefixMatchElements = new ArrayList<>(objects.size());
|
||||
List<PsiElement> curElements = prefixMatchElements;
|
||||
for (Object object : objects) {
|
||||
if (object instanceof PsiElement) {
|
||||
@@ -782,7 +782,7 @@ public abstract class ChooseByNameBase {
|
||||
close(ok);
|
||||
|
||||
clearPostponedOkAction(ok);
|
||||
myListModel.clear();
|
||||
myListModel.removeAll();
|
||||
}
|
||||
|
||||
protected boolean closeForbidden(boolean ok) {
|
||||
@@ -973,7 +973,7 @@ public abstract class ChooseByNameBase {
|
||||
|
||||
final String text = getTrimmedText();
|
||||
if (!canShowListForEmptyPattern() && text.isEmpty()) {
|
||||
myListModel.clear();
|
||||
myListModel.removeAll();
|
||||
hideList();
|
||||
myTextFieldPanel.hideHint();
|
||||
myCard.show(myCardContainer, CHECK_BOX_CARD);
|
||||
@@ -1033,7 +1033,7 @@ public abstract class ChooseByNameBase {
|
||||
}
|
||||
}
|
||||
if (elements.isEmpty()) {
|
||||
myListModel.clear();
|
||||
myListModel.removeAll();
|
||||
myTextField.setForeground(JBColor.red);
|
||||
myListUpdater.cancelAll();
|
||||
hideList();
|
||||
@@ -1041,7 +1041,7 @@ public abstract class ChooseByNameBase {
|
||||
return;
|
||||
}
|
||||
|
||||
Object[] oldElements = myListModel.toArray();
|
||||
Object[] oldElements = myListModel.getItems().toArray();
|
||||
Object[] newElements = elements.toArray();
|
||||
List<ModelDiff.Cmd> commands = ModelDiff.createDiffCmds(myListModel, oldElements, newElements);
|
||||
if (commands == null) {
|
||||
@@ -1055,7 +1055,7 @@ public abstract class ChooseByNameBase {
|
||||
pos = calcSelectedIndex(newElements, getTrimmedText());
|
||||
}
|
||||
|
||||
ScrollingUtil.selectItem(myList, Math.min(pos, myListModel.size() - 1));
|
||||
ScrollingUtil.selectItem(myList, Math.min(pos, myListModel.getSize() - 1));
|
||||
myList.setVisibleRowCount(Math.min(VISIBLE_LIST_SIZE_LIMIT, myList.getModel().getSize()));
|
||||
showList();
|
||||
myTextFieldPanel.repositionHint();
|
||||
@@ -1113,21 +1113,21 @@ public abstract class ChooseByNameBase {
|
||||
return "choose_by_name#" + myModel.getPromptText() + "#" + myCheckBox.isSelected() + "#" + getTrimmedText();
|
||||
}
|
||||
|
||||
private static class MyListModel<T> extends DefaultListModel implements ModelDiff.Model<T> {
|
||||
private static class MyListModel<T> extends CollectionListModel<T> implements ModelDiff.Model<T> {
|
||||
@Override
|
||||
public void addToModel(int idx, T element) {
|
||||
if (idx < size()) {
|
||||
add(idx, element);
|
||||
}
|
||||
else {
|
||||
addElement(element);
|
||||
}
|
||||
add(Math.min(idx, getSize()), element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllToModel(int index, List<T> elements) {
|
||||
addAll(Math.min(index, getSize()), elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRangeFromModel(int start, int end) {
|
||||
if (start < size() && size() != 0) {
|
||||
removeRange(start, Math.min(end, size()-1));
|
||||
if (start < getSize() && !isEmpty()) {
|
||||
removeRange(start, Math.min(end, getSize() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1175,8 +1175,8 @@ public abstract class ChooseByNameBase {
|
||||
myTextFieldPanel.repositionHint();
|
||||
|
||||
if (!myListModel.isEmpty()) {
|
||||
int pos = selectionPos <= 0 ? calcSelectedIndex(myListModel.toArray(), ChooseByNameBase.this.getTrimmedText()) : selectionPos;
|
||||
ScrollingUtil.selectItem(myList, Math.min(pos, myListModel.size() - 1));
|
||||
int pos = selectionPos <= 0 ? calcSelectedIndex(myListModel.getItems().toArray(), ChooseByNameBase.this.getTrimmedText()) : selectionPos;
|
||||
ScrollingUtil.selectItem(myList, Math.min(pos, myListModel.getSize() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ModelDiff {
|
||||
@@ -48,9 +49,8 @@ public class ModelDiff {
|
||||
}
|
||||
|
||||
if (change.inserted > 0) {
|
||||
for (int i = 0; i < change.inserted; i++) {
|
||||
commands.add(new InsertCmd<>(listModel, change.line0 + i + inserted - deleted, newElements[change.line1 + i]));
|
||||
}
|
||||
List<Object> elements = new ArrayList<>(Arrays.asList(newElements).subList(change.line1, change.line1 + change.inserted));
|
||||
commands.add(new InsertCmd<>(listModel, change.line0 + inserted - deleted, elements));
|
||||
}
|
||||
|
||||
deleted += change.deleted;
|
||||
@@ -67,6 +67,13 @@ public class ModelDiff {
|
||||
|
||||
public interface Model<T> {
|
||||
void addToModel(int index, T element);
|
||||
|
||||
default void addAllToModel(int index, List<T> elements) {
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
addToModel(index + i, elements.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
void removeRangeFromModel(int start, int end);
|
||||
}
|
||||
|
||||
@@ -102,18 +109,18 @@ public class ModelDiff {
|
||||
private static class InsertCmd<T> implements Cmd {
|
||||
private final Model<T> myListModel;
|
||||
private final int idx;
|
||||
private final T element;
|
||||
private final List<T> elements;
|
||||
|
||||
private InsertCmd(@NotNull Model<T> model, final int idx, @NotNull T element) {
|
||||
private InsertCmd(@NotNull Model<T> model, final int idx, @NotNull List<T> elements) {
|
||||
myListModel = model;
|
||||
this.idx = idx;
|
||||
this.element = element;
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
//System.out.println("Adding: "+this+"-> "+element);
|
||||
myListModel.addToModel(idx, element);
|
||||
myListModel.addAllToModel(idx, elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -66,7 +66,4 @@ public class CollectionComboBoxModel<T> extends CollectionListModel<T> implement
|
||||
super.fireContentsChanged(this, -1, -1);
|
||||
}
|
||||
|
||||
public boolean contains(T item) {
|
||||
return getElementIndex(item) != -1;
|
||||
}
|
||||
}
|
||||
@@ -75,10 +75,14 @@ public class CollectionListModel<T> extends AbstractListModel<T> implements Edit
|
||||
}
|
||||
|
||||
public void add(@NotNull final List<? extends T> elements) {
|
||||
addAll(myItems.size(), elements);
|
||||
}
|
||||
|
||||
public void addAll(int index, @NotNull final List<? extends T> elements) {
|
||||
if (elements.isEmpty()) return;
|
||||
int i = myItems.size();
|
||||
myItems.addAll(elements);
|
||||
fireIntervalAdded(this, i, i + elements.size() - 1);
|
||||
|
||||
myItems.addAll(index, elements);
|
||||
fireIntervalAdded(this, index, index + elements.size() - 1);
|
||||
}
|
||||
|
||||
public void remove(@NotNull T element) {
|
||||
@@ -167,4 +171,19 @@ public class CollectionListModel<T> extends AbstractListModel<T> implements Edit
|
||||
public boolean isEmpty() {
|
||||
return myItems.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(T item) {
|
||||
return getElementIndex(item) >= 0;
|
||||
}
|
||||
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
if (fromIndex > toIndex) {
|
||||
throw new IllegalArgumentException("fromIndex must be <= toIndex");
|
||||
}
|
||||
for(int i = toIndex; i >= fromIndex; i--) {
|
||||
itemReplaced(myItems.remove(i), null);
|
||||
}
|
||||
fireIntervalRemoved(this, fromIndex, toIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -592,4 +592,14 @@ public class ReflectionUtil {
|
||||
return JBIterable.of(aClass.getSuperclass()).append(aClass.getInterfaces());
|
||||
}
|
||||
};
|
||||
|
||||
private static final Method DEFINE_CLASS =
|
||||
ObjectUtils.assertNotNull(getDeclaredMethod(ClassLoader.class, "defineClass", String.class, byte[].class, int.class, int.class));
|
||||
|
||||
public static Class defineClass(@NotNull String className, @NotNull byte[] bytes, ClassLoader loader) throws Exception {
|
||||
Class c = (Class)DEFINE_CLASS.invoke(loader, className, bytes, 0, bytes.length);
|
||||
Class.forName(className, true, loader);
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user