mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Binary file not shown.
@@ -37,7 +37,6 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CompilerUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompilerUtil");
|
||||
@@ -74,7 +73,7 @@ public class CompilerUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshOutputDirectories(Set<File> outputs, boolean async) {
|
||||
public static void refreshOutputDirectories(Collection<File> outputs, boolean async) {
|
||||
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
|
||||
List<VirtualFile> toRefresh = new ArrayList<VirtualFile>();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.compiler.server;
|
||||
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.compiler.CompilerWorkspaceConfiguration;
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration;
|
||||
import com.intellij.compiler.server.impl.BuildProcessClasspathManager;
|
||||
import com.intellij.execution.ExecutionAdapter;
|
||||
@@ -1266,26 +1267,39 @@ public class BuildManager implements ApplicationComponent{
|
||||
roots = ArrayUtil.toStringArray(myRootsToRefresh);
|
||||
myRootsToRefresh.clear();
|
||||
}
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
final Set<VirtualFile> filesToRefresh = new HashSet<VirtualFile>();
|
||||
for (String root : roots) {
|
||||
final VirtualFile rootFile = lfs.refreshAndFindFileByPath(root);
|
||||
if (rootFile != null && fileIndex.isInSourceContent(rootFile)) {
|
||||
filesToRefresh.add(rootFile);
|
||||
if (roots.length != 0) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
final List<File> rootFiles = new ArrayList<File>(roots.length);
|
||||
for (String root : roots) {
|
||||
rootFiles.add(new File(root));
|
||||
}
|
||||
// this will ensure that we'll be able to obtain VirtualFile for existing roots
|
||||
CompilerUtil.refreshOutputDirectories(rootFiles, false);
|
||||
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
final Set<VirtualFile> filesToRefresh = new HashSet<VirtualFile>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
for (File root : rootFiles) {
|
||||
final VirtualFile rootFile = lfs.findFileByIoFile(root);
|
||||
if (rootFile != null && fileIndex.isInSourceContent(rootFile)) {
|
||||
filesToRefresh.add(rootFile);
|
||||
}
|
||||
}
|
||||
if (!filesToRefresh.isEmpty()) {
|
||||
lfs.refreshFiles(filesToRefresh, true, true, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!filesToRefresh.isEmpty()) {
|
||||
lfs.refreshFiles(filesToRefresh, true, true, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -651,10 +651,11 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && isEffectivelyFinal(variable, innerClass, context)) {
|
||||
final boolean isToBeEffectivelyFinal = languageLevel.isAtLeast(LanguageLevel.JDK_1_8);
|
||||
if (isToBeEffectivelyFinal && isEffectivelyFinal(variable, innerClass, context)) {
|
||||
return null;
|
||||
}
|
||||
final String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
|
||||
final String description = JavaErrorMessages.message(isToBeEffectivelyFinal ? "variable.must.be.final.or.effectively.final" : "variable.must.be.final", context.getText());
|
||||
|
||||
final HighlightInfo highlightInfo =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip(description).create();
|
||||
|
||||
+2
-1
@@ -915,7 +915,8 @@ public class HighlightMethodUtil {
|
||||
PsiType paramType = i < parameters.length && parameters[i] != null
|
||||
? substitutor.substitute(parameters[i].getType())
|
||||
: null;
|
||||
return paramType != null && TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression);
|
||||
PsiType expressionType = expression.getType();
|
||||
return paramType != null && expressionType != null && TypeConversionUtil.isAssignable(paramType, expressionType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-4
@@ -79,6 +79,7 @@ public class CreateFromUsageUtils {
|
||||
private static final Logger LOG = Logger.getInstance(
|
||||
"#com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils");
|
||||
private static final int MAX_GUESSED_MEMBERS_COUNT = 10;
|
||||
private static final int MAX_RAW_GUESSED_MEMBERS_COUNT = 2 * MAX_GUESSED_MEMBERS_COUNT;
|
||||
|
||||
public static boolean isValidReference(PsiReference reference, boolean unresolvedOnly) {
|
||||
if (!(reference instanceof PsiJavaReference)) return false;
|
||||
@@ -671,12 +672,12 @@ public class CreateFromUsageUtils {
|
||||
final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(expression.getProject());
|
||||
PsiElementFactory factory = facade.getElementFactory();
|
||||
for (String fieldName : expectedFieldNames) {
|
||||
PsiField[] fields = cache.getFieldsByName(fieldName, resolveScope);
|
||||
PsiField[] fields = cache.getFieldsByNameIfNotMoreThan(fieldName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT);
|
||||
addMemberInfo(fields, expression, typesList, factory);
|
||||
}
|
||||
|
||||
for (String methodName : expectedMethodNames) {
|
||||
PsiMethod[] methods = cache.getMethodsByName(methodName, resolveScope);
|
||||
PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(methodName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT);
|
||||
addMemberInfo(methods, expression, typesList, factory);
|
||||
}
|
||||
}
|
||||
@@ -723,12 +724,12 @@ public class CreateFromUsageUtils {
|
||||
final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(expression.getProject());
|
||||
PsiElementFactory factory = facade.getElementFactory();
|
||||
for (String fieldName : expectedFieldNames) {
|
||||
PsiField[] fields = cache.getFieldsByName(fieldName, resolveScope);
|
||||
PsiField[] fields = cache.getFieldsByNameIfNotMoreThan(fieldName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT);
|
||||
addMemberInfo(fields, expression, typesList, factory);
|
||||
}
|
||||
|
||||
for (String methodName : expectedMethodNames) {
|
||||
PsiMethod[] methods = cache.getMethodsByName(methodName, resolveScope);
|
||||
PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(methodName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT);
|
||||
addMemberInfo(methods, expression, typesList, factory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.tree.ChildRoleBase;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.CharTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -111,6 +112,9 @@ public class ClassElement extends CompositeElement implements Constants {
|
||||
for (ASTNode run = anchor; run != null; run = run.getTreeNext()) {
|
||||
if (run == semicolonPlace) {
|
||||
anchor = before.booleanValue() ? semicolonPlace.getTreeNext() : semicolonPlace;
|
||||
if (anchor != null && PsiImplUtil.isWhitespaceOrComment(anchor)) {
|
||||
anchor = PsiTreeUtil.skipSiblingsForward(anchor.getPsi(), PsiWhiteSpace.class, PsiComment.class).getNode();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ variable.already.assigned=Variable ''{0}'' might already have been assigned to
|
||||
variable.assigned.in.loop=Variable ''{0}'' might be assigned in loop
|
||||
assignment.to.final.variable=Cannot assign a value to final variable ''{0}''
|
||||
variable.must.be.final=Variable ''{0}'' is accessed from within inner class, needs to be declared final
|
||||
variable.must.be.final.or.effectively.final=Variable ''{0}'' is accessed from within inner class, needs to be final or effectively final
|
||||
initializer.must.be.able.to.complete.normally=Initializer must be able to complete normally
|
||||
weaker.privileges={0}; attempting to assign weaker access privileges (''{1}''); was ''{2}''
|
||||
incompatible.return.type=attempting to use incompatible return type
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ class ParameterIsEffectivelyFinal {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println(<error descr="Variable 'o' is accessed from within inner class, needs to be declared final">o</error>);
|
||||
System.out.println(<error descr="Variable 'o' is accessed from within inner class, needs to be final or effectively final">o</error>);
|
||||
}
|
||||
}.run();
|
||||
return 0;
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Create Field for Parameter 'p1'" "true"
|
||||
|
||||
enum Test{
|
||||
A;//comment
|
||||
|
||||
private int myP1;
|
||||
|
||||
void f(int p1){
|
||||
myP1 = p1;
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Create Field for Parameter 'p1'" "true"
|
||||
|
||||
enum Test{
|
||||
A;//comment
|
||||
|
||||
void f(int p<caret>1){
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ Compiling files:
|
||||
src/A.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/AddMethod/C.class
|
||||
out/production/AddMethod/D.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/C.java
|
||||
src/D.java
|
||||
End of files
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/AddVarargMethod/A.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/A.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/AddVarargMethod/C.class
|
||||
out/production/AddVarargMethod/D.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/C.java
|
||||
src/D.java
|
||||
End of files
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class A {
|
||||
void f (String x, Integer y) {
|
||||
|
||||
}
|
||||
|
||||
void f (String x, Integer y, Long z, String... v){
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class A {
|
||||
void f (String x, Integer y, String... v) {
|
||||
|
||||
}
|
||||
|
||||
void f (String x, Integer y, Long z, String... v){
|
||||
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class C {
|
||||
void f (A a){
|
||||
a.f("1", 2);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class D {
|
||||
void f(A a){
|
||||
a.f("1", 2, null, "comment");
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -75,12 +75,13 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testNestedCallsInsideLambdaReturnExpression() { doTest(); }
|
||||
public void testIDEA123731() { doTest(); }
|
||||
public void testIDEA123869() { doTest(); }
|
||||
@Bombed(day = 30, month = Calendar.NOVEMBER)
|
||||
public void testIDEA123848() { doTest(); }
|
||||
public void testOnlyLambdaAtTypeParameterPlace() { doTest(); }
|
||||
public void testLiftedIntersectionType() { doTest(); }
|
||||
public void testInferenceFromReturnStatements() { doTest(); }
|
||||
public void testDownUpThroughLambdaReturnStatements() { doTest(); }
|
||||
@Bombed(day = 30, month = Calendar.OCTOBER)
|
||||
@Bombed(day = 30, month = Calendar.NOVEMBER)
|
||||
public void testIDEA124547() { doTest(); }
|
||||
public void testIDEA118362() { doTest(); }
|
||||
public void testIDEA126056() { doTest(); }
|
||||
@@ -134,7 +135,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Bombed(month = Calendar.OCTOBER, day = 30)
|
||||
@Bombed(month = Calendar.NOVEMBER, day = 30)
|
||||
public void testCheckedExceptionsConstraintsSubstitutions() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
+3
-3
@@ -173,7 +173,7 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
|
||||
myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className));
|
||||
|
||||
myUsedArguments.add(methodName);
|
||||
}
|
||||
@@ -183,7 +183,7 @@ class ClassfileAnalyzer {
|
||||
final String methodDescr = "()" + desc;
|
||||
|
||||
myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className));
|
||||
|
||||
myUsedArguments.add(methodName);
|
||||
}
|
||||
@@ -526,7 +526,7 @@ class ClassfileAnalyzer {
|
||||
final int methodOwner = myContext.get(owner);
|
||||
|
||||
myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner, desc));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner));
|
||||
addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc)));
|
||||
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
|
||||
@@ -400,16 +400,31 @@ public class Mappings {
|
||||
|
||||
private boolean hasOverriddenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate) {
|
||||
for (int superName : fromClass.getSupers()) {
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
if (superClass == null) {
|
||||
return true; // assumption
|
||||
if (superName == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
for (MethodRepr mm : superClass.findMethods(predicate)) {
|
||||
if (isVisibleIn(superClass, mm, fromClass)) {
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
if (superClass != null) {
|
||||
for (MethodRepr mm : superClass.findMethods(predicate)) {
|
||||
if (isVisibleIn(superClass, mm, fromClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (hasOverriddenMethods(superClass, predicate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (hasOverriddenMethods(superClass, predicate)) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean extendsLibraryClass(final ClassRepr fromClass) {
|
||||
for (int superName : fromClass.getSupers()) {
|
||||
if (superName != myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
if (superClass == null || extendsLibraryClass(superClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -440,6 +455,9 @@ public class Mappings {
|
||||
|
||||
void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection<Pair<FieldRepr, ClassRepr>> container) {
|
||||
for (int supername : fromClass.getSupers()) {
|
||||
if (supername == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(supername);
|
||||
if (superClass != null) {
|
||||
final FieldRepr ff = superClass.findField(f.name);
|
||||
@@ -455,6 +473,9 @@ public class Mappings {
|
||||
|
||||
boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) {
|
||||
for (int supername : fromClass.getSupers()) {
|
||||
if (supername == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(supername);
|
||||
if (superClass != null) {
|
||||
final FieldRepr ff = superClass.findField(f.name);
|
||||
@@ -534,15 +555,8 @@ public class Mappings {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
boolean isMethodVisible(final int className, final MethodRepr m) {
|
||||
final ClassRepr r = reprByName(className);
|
||||
if (r != null) {
|
||||
if (r.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0) {
|
||||
return true;
|
||||
}
|
||||
return hasOverriddenMethods(r, MethodRepr.equalByJavaRules(m));
|
||||
}
|
||||
return false;
|
||||
boolean isMethodVisible(final ClassRepr classRepr, final MethodRepr m) {
|
||||
return classRepr.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0 || hasOverriddenMethods(classRepr, MethodRepr.equalByJavaRules(m));
|
||||
}
|
||||
|
||||
boolean isFieldVisible(final int className, final FieldRepr field) {
|
||||
@@ -1082,10 +1096,7 @@ public class Mappings {
|
||||
}
|
||||
final ClassRepr oldIt = oldItRef.get();
|
||||
|
||||
if (oldIt != null && myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) {
|
||||
|
||||
}
|
||||
else {
|
||||
if (oldIt == null || !myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) {
|
||||
if (m.myArgumentTypes.length > 0) {
|
||||
propagated = myFuture.propagateMethodAccess(m, it.name);
|
||||
debug("Conservative case on overriding methods, affecting method usages");
|
||||
@@ -1170,10 +1181,13 @@ public class Mappings {
|
||||
final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
|
||||
final int outerClass = r.getOuterClassName();
|
||||
if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting file due to local overriding: ", sourceFileName);
|
||||
if (!isEmpty(outerClass)) {
|
||||
final ClassRepr outerClassRepr = myFuture.reprByName(outerClass);
|
||||
if (outerClassRepr != null && (myFuture.isMethodVisible(outerClassRepr, m) || myFuture.extendsLibraryClass(outerClassRepr))) {
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting file due to local overriding: ", sourceFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -112,8 +112,8 @@ class MethodRepr extends ProtoMember {
|
||||
public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
|
||||
myType.updateClassUsages(context, owner, s);
|
||||
|
||||
for (int i = 0; i < myArgumentTypes.length; i++) {
|
||||
myArgumentTypes[i].updateClassUsages(context, owner, s);
|
||||
for (final TypeRepr.AbstractType argType : myArgumentTypes) {
|
||||
argType.updateClassUsages(context, owner, s);
|
||||
}
|
||||
|
||||
if (myExceptions != null) {
|
||||
@@ -124,17 +124,17 @@ class MethodRepr extends ProtoMember {
|
||||
}
|
||||
|
||||
public MethodRepr(final DependencyContext context,
|
||||
final int a,
|
||||
final int n,
|
||||
final int s,
|
||||
final String d,
|
||||
final String[] e,
|
||||
final Object value) {
|
||||
super(a, s, n, TypeRepr.getType(context, Type.getReturnType(d)), value);
|
||||
final int accessFlags,
|
||||
final int name,
|
||||
final int signature,
|
||||
final String descriptor,
|
||||
final String[] exceptions,
|
||||
final Object defaultValue) {
|
||||
super(accessFlags, signature, name, TypeRepr.getType(context, Type.getReturnType(descriptor)), defaultValue);
|
||||
Set<TypeRepr.AbstractType> typeCollection =
|
||||
e != null ? new THashSet<TypeRepr.AbstractType>(e.length) : Collections.<TypeRepr.AbstractType>emptySet();
|
||||
myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, e, typeCollection);
|
||||
myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(d));
|
||||
exceptions != null ? new THashSet<TypeRepr.AbstractType>(exceptions.length) : Collections.<TypeRepr.AbstractType>emptySet();
|
||||
myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, exceptions, typeCollection);
|
||||
myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(descriptor));
|
||||
}
|
||||
|
||||
public MethodRepr(final DependencyContext context, final DataInput in) {
|
||||
@@ -216,7 +216,7 @@ class MethodRepr extends ProtoMember {
|
||||
}
|
||||
|
||||
public UsageRepr.Usage createMetaUsage(final DependencyContext context, final int owner) {
|
||||
return UsageRepr.createMetaMethodUsage(context, name, owner, getDescr(context));
|
||||
return UsageRepr.createMetaMethodUsage(context, name, owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -278,52 +278,18 @@ class UsageRepr {
|
||||
}
|
||||
|
||||
public static class MetaMethodUsage extends FMUsage {
|
||||
private int myArity;
|
||||
|
||||
public MetaMethodUsage(final DependencyContext context, final int n, final int o, final String descr) {
|
||||
public MetaMethodUsage(final int n, final int o) {
|
||||
super(n, o);
|
||||
myArity = TypeRepr.getType(context, Type.getArgumentTypes(descr)).length;
|
||||
}
|
||||
|
||||
public MetaMethodUsage(final DataInput in) {
|
||||
super(in);
|
||||
try {
|
||||
myArity = DataInputOutputUtil.readINT(in);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out) {
|
||||
save(METAMETHOD_USAGE, out);
|
||||
try {
|
||||
DataInputOutputUtil.writeINT(out, myArity);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
MetaMethodUsage that = (MetaMethodUsage)o;
|
||||
|
||||
if (myArity != that.myArity) return false;
|
||||
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + myArity;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -334,7 +300,6 @@ class UsageRepr {
|
||||
@Override
|
||||
public void toStream(DependencyContext context, PrintStream stream) {
|
||||
super.toStream(context, stream);
|
||||
stream.println(" Arity: " + Integer.toString(myArity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,8 +644,8 @@ class UsageRepr {
|
||||
return context.getUsage(new MethodUsage(context, name, owner, descr));
|
||||
}
|
||||
|
||||
public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner, final String descr) {
|
||||
return context.getUsage(new MetaMethodUsage(context, name, owner, descr));
|
||||
public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner) {
|
||||
return context.getUsage(new MetaMethodUsage(name, owner));
|
||||
}
|
||||
|
||||
public static Usage createClassUsage(final DependencyContext context, final int name) {
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* Date: 10/7/11
|
||||
*/
|
||||
public class BuildDataManager implements StorageOwner {
|
||||
private static final int VERSION = 25;
|
||||
private static final int VERSION = 26;
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
|
||||
private static final String SRC_TO_FORM_STORAGE = "src-form";
|
||||
private static final String OUT_TARGET_STORAGE = "out-target";
|
||||
|
||||
@@ -203,4 +203,8 @@ public class MemberChangeTest extends IncrementalTestCase {
|
||||
public void testAddMethod() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAddVarargMethod() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Clang can be downloaded from http://llvm.org/releases/download.html or found in XCode 4+
|
||||
clang -arch i386 -mmacosx-version-min=10.5 -framework CoreServices -o fsnotifier fsnotifier.c
|
||||
clang -arch i386 -arch x86_64 -mmacosx-version-min=10.5 -framework CoreServices -o fsnotifier fsnotifier.c
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 5.0 KiB |
@@ -19,6 +19,7 @@ import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.content.Content;
|
||||
@@ -26,9 +27,8 @@ import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.ui.content.ContentManagerAdapter;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.ui.switcher.QuickActionProvider;
|
||||
import com.intellij.ui.tabs.JBTabs;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.AwtVisitor;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -38,7 +38,6 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ContainerAdapter;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider, DataProvider {
|
||||
@@ -199,14 +198,6 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
|
||||
component instanceof DataProvider ? PlatformDataKeys.CONTENT_MANAGER.getData((DataProvider)component) : null;
|
||||
if (contentManager != null) contentManager.addContentManagerListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged(ContentManagerEvent event) {
|
||||
Content content = event.getContent();
|
||||
if (content != null) {
|
||||
setContentToolbarVisible(content.getComponent(), getVisibilityValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -233,18 +224,8 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
|
||||
}
|
||||
|
||||
private static void setContentToolbarVisible(@NotNull JComponent root, boolean state) {
|
||||
LinkedList<JComponent> deque = ContainerUtil.newLinkedList(root);
|
||||
while(!deque.isEmpty()) {
|
||||
JComponent component = deque.pollFirst();
|
||||
for (int i = 0, count = component.getComponentCount(); i < count; i++) {
|
||||
Component c = component.getComponent(i);
|
||||
if (c instanceof ActionToolbar) {
|
||||
c.setVisible(state);
|
||||
}
|
||||
else if (c instanceof JPanel || c instanceof JLayeredPane || c instanceof JBTabs) {
|
||||
deque.addLast((JComponent)c);
|
||||
}
|
||||
}
|
||||
for (Component c : JBSwingUtilities.uiTraverser().preOrderTraversal(root).filter(Conditions.instanceOf(ActionToolbar.class))) {
|
||||
c.setVisible(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public interface OrphanGuardian {
|
||||
Key CLIENT_PROPERTY_KEY = Key.create("OrphanGuardian");
|
||||
|
||||
void iterateOrphans(Consumer<JComponent> processor);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import com.intellij.util.ui.EmptyIcon;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -41,7 +42,12 @@ public class ActionLink extends LinkLabel implements DataProvider {
|
||||
public ActionLink(String text, @NotNull AnAction action) {
|
||||
this(text, ICON, action);
|
||||
}
|
||||
|
||||
public ActionLink(String text, Icon icon, @NotNull AnAction action) {
|
||||
this(text, icon, action, null);
|
||||
}
|
||||
|
||||
public ActionLink(String text, Icon icon, @NotNull AnAction action, @Nullable final Runnable onDone) {
|
||||
super(text, icon);
|
||||
setListener(new LinkListener() {
|
||||
@Override
|
||||
@@ -56,6 +62,9 @@ public class ActionLink extends LinkLabel implements DataProvider {
|
||||
myAction.update(event);
|
||||
if (event.getPresentation().isEnabled() && event.getPresentation().isVisible()) {
|
||||
myAction.actionPerformed(event);
|
||||
if (onDone != null) {
|
||||
onDone.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.openapi.wm.*;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
import com.intellij.ui.components.OrphanGuardian;
|
||||
import com.intellij.ui.switcher.QuickActionProvider;
|
||||
import com.intellij.ui.switcher.SwitchProvider;
|
||||
import com.intellij.ui.switcher.SwitchTarget;
|
||||
@@ -37,13 +36,10 @@ import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout;
|
||||
import com.intellij.ui.tabs.impl.singleRow.SingleRowPassInfo;
|
||||
import com.intellij.ui.tabs.impl.table.TableLayout;
|
||||
import com.intellij.ui.tabs.impl.table.TablePassInfo;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.Animator;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
import com.intellij.util.ui.TimedDeadzone;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.containers.FluentIterable;
|
||||
import com.intellij.util.ui.*;
|
||||
import com.intellij.util.ui.update.ComparableObject;
|
||||
import com.intellij.util.ui.update.LazyUiDisposable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -316,16 +312,19 @@ public class JBTabsImpl extends JComponent
|
||||
}
|
||||
}
|
||||
};
|
||||
putClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY, new OrphanGuardian() {
|
||||
|
||||
@Override
|
||||
public void iterateOrphans(Consumer<JComponent> consumer) {
|
||||
for (TabInfo info : getVisibleInfos()) {
|
||||
if (info == mySelectedInfo) continue;
|
||||
consumer.consume(info.getComponent());
|
||||
UIUtil.putClientProperty(
|
||||
this, JBSwingUtilities.NOT_IN_HIERARCHY_COMPONENTS, new Iterable<JComponent>() {
|
||||
@Override
|
||||
public Iterator<JComponent> iterator() {
|
||||
return FluentIterable.from(getVisibleInfos()).filter(Conditions.not(Conditions.is(mySelectedInfo))).transform(
|
||||
new Function<TabInfo, JComponent>() {
|
||||
@Override
|
||||
public JComponent fun(TabInfo info) {
|
||||
return info.getComponent();
|
||||
}
|
||||
}).iterator();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected SingleRowLayout createSingleRowLayout() {
|
||||
|
||||
+4
-1
@@ -19,6 +19,8 @@ import com.intellij.openapi.command.undo.DocumentReference;
|
||||
import com.intellij.openapi.command.undo.DocumentReferenceManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.WeakList;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -41,7 +43,8 @@ class UndoRedoStacksHolder {
|
||||
|
||||
@NotNull
|
||||
LinkedList<UndoableGroup> getStack(@NotNull DocumentReference r) {
|
||||
return r.getFile() != null ? doGetStackForFile(r) : doGetStackForDocument(r);
|
||||
VirtualFile file = r.getFile();
|
||||
return file != null && !(file instanceof LightVirtualFile) ? doGetStackForFile(r) : doGetStackForDocument(r);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -74,7 +74,6 @@ import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBLayeredPane;
|
||||
import com.intellij.ui.components.JBScrollBar;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.ui.components.OrphanGuardian;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
@@ -491,16 +490,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myVerticalScrollBar = (MyScrollBar)myScrollPane.getVerticalScrollBar();
|
||||
myPanel = new JPanel();
|
||||
|
||||
myPanel.putClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY, new OrphanGuardian() {
|
||||
|
||||
@Override
|
||||
public void iterateOrphans(Consumer<JComponent> consumer) {
|
||||
JComponent component = getPermanentHeaderComponent();
|
||||
if (component != null && !component.isValid()) {
|
||||
consumer.consume(component);
|
||||
UIUtil.putClientProperty(
|
||||
myPanel, JBSwingUtilities.NOT_IN_HIERARCHY_COMPONENTS, new Iterable<JComponent>() {
|
||||
@Override
|
||||
public Iterator<JComponent> iterator() {
|
||||
JComponent component = getPermanentHeaderComponent();
|
||||
if (component != null && !component.isValid()) {
|
||||
return Collections.singleton(component).iterator();
|
||||
}
|
||||
return ContainerUtil.emptyIterator();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
myHeaderPanel = new MyHeaderPanel();
|
||||
myGutterComponent = new EditorGutterComponentImpl(this);
|
||||
|
||||
+39
-26
@@ -17,7 +17,8 @@ package com.intellij.openapi.wm.impl.welcomeScreen;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.RecentProjectsManager;
|
||||
import com.intellij.ide.RecentProjectsManagerBase;
|
||||
import com.intellij.internal.statistic.UsageTrigger;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.MnemonicHelper;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
@@ -88,7 +89,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
setTitle("Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName());
|
||||
AppUIUtil.updateWindowIcon(this);
|
||||
//Rectangle bounds = ScreenUtil.getMainScreenBounds();
|
||||
if (RecentProjectsManager.getInstance().getRecentProjectsActions(false).length > 0) {
|
||||
if (RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length > 0) {
|
||||
setSize(666, 460);
|
||||
} else {
|
||||
setSize(555, 460);
|
||||
@@ -166,23 +167,23 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
public StatusBar getStatusBar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static Color getMainBackground() {
|
||||
return new JBColor(0xf7f7f7, 0x45474a);
|
||||
}
|
||||
|
||||
|
||||
public static Color getProjectsBackground() {
|
||||
return new JBColor(Gray.xFF, Gray.x39);
|
||||
}
|
||||
|
||||
|
||||
public static Color getLinkNormalColor() {
|
||||
return new JBColor(Gray._0, Gray.xBB);
|
||||
}
|
||||
|
||||
|
||||
public static Color getListSelectionColor(boolean hasFocus) {
|
||||
return hasFocus ? new JBColor(0x3875d6, 0x4b6eaf) : new JBColor(Gray.xDD, Gray.x45);
|
||||
}
|
||||
|
||||
|
||||
public static Color getActionLinkSelectionColor() {
|
||||
return new JBColor(0xdbe5f5, 0x485875);
|
||||
}
|
||||
@@ -195,14 +196,14 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
public FlatWelcomeScreen() {
|
||||
super(new BorderLayout());
|
||||
setBackground(getMainBackground());
|
||||
if (RecentProjectsManager.getInstance().getRecentProjectsActions(false).length > 0) {
|
||||
if (RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length > 0) {
|
||||
final JComponent recentProjects = createRecentProjects();
|
||||
add(recentProjects, BorderLayout.WEST);
|
||||
final JList projectsList = UIUtil.findComponentOfType(recentProjects, JList.class);
|
||||
if (projectsList != null) {
|
||||
projectsList.getModel().addListDataListener(new ListDataListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,7 +212,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
}
|
||||
|
||||
private void removeIfNeeded() {
|
||||
if (RecentProjectsManager.getInstance().getRecentProjectsActions(false).length == 0) {
|
||||
if (RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length == 0) {
|
||||
FlatWelcomeScreen.this.remove(recentProjects);
|
||||
FlatWelcomeScreen.this.revalidate();
|
||||
FlatWelcomeScreen.this.repaint();
|
||||
@@ -260,7 +261,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
if (register != null) {
|
||||
Presentation presentation = register.getTemplatePresentation();
|
||||
register.update(new AnActionEvent(null, DataManager.getInstance().getDataContext(this),
|
||||
ActionPlaces.WELCOME_SCREEN, presentation, ActionManager.getInstance(), 0));
|
||||
ActionPlaces.WELCOME_SCREEN, presentation, ActionManager.getInstance(), 0));
|
||||
if (presentation.isEnabled()) {
|
||||
ActionLink registerLink = new ActionLink("Register", register);
|
||||
registerLink.setNormalColor(getLinkNormalColor());
|
||||
@@ -279,14 +280,14 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS));
|
||||
toolbar.add(createActionLink("Configure", IdeActions.GROUP_WELCOME_SCREEN_CONFIGURE, AllIcons.General.GearPlain, !registeredVisible));
|
||||
toolbar.add(createActionLink("Get Help", IdeActions.GROUP_WELCOME_SCREEN_DOC, null, false));
|
||||
|
||||
|
||||
panel.add(toolbar, BorderLayout.EAST);
|
||||
|
||||
|
||||
|
||||
panel.setBorder(new EmptyBorder(0,0,8,11));
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
private JComponent createActionLink(final String text, final String groupId, Icon icon, boolean focusListOnLeft) {
|
||||
final Ref<ActionLink> ref = new Ref<ActionLink>(null);
|
||||
AnAction action = new AnAction() {
|
||||
@@ -294,8 +295,10 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
ActionGroup configureGroup = (ActionGroup)ActionManager.getInstance().getAction(groupId);
|
||||
final PopupFactoryImpl.ActionGroupPopup popup = (PopupFactoryImpl.ActionGroupPopup)JBPopupFactory.getInstance()
|
||||
.createActionGroupPopup(null, new IconsFreeActionGroup(configureGroup), e.getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false, ActionPlaces.WELCOME_SCREEN);
|
||||
.createActionGroupPopup(null, new IconsFreeActionGroup(configureGroup), e.getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false,
|
||||
ActionPlaces.WELCOME_SCREEN);
|
||||
popup.showUnderneathOfLabel(ref.get());
|
||||
UsageTrigger.trigger("welcome.screen." + groupId);
|
||||
}
|
||||
};
|
||||
ref.set(new ActionLink(text, icon, action));
|
||||
@@ -334,7 +337,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
if (icon.getIconHeight() != 16 || icon.getIconWidth() != 16) {
|
||||
icon = EmptyIcon.ICON_16;
|
||||
}
|
||||
ActionLink link = new ActionLink(text, icon, action);
|
||||
ActionLink link = new ActionLink(text, icon, action, createUsageTracker(action));
|
||||
link.setPaintUnderline(false);
|
||||
link.setNormalColor(getLinkNormalColor());
|
||||
button.add(link);
|
||||
@@ -374,16 +377,16 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
appName.setFont(font.deriveFont(36f).deriveFont(Font.PLAIN));
|
||||
appName.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
String appVersion = "Version " + app.getFullVersion();
|
||||
|
||||
|
||||
if (app.isEAP() && app.getBuild().getBuildNumber() < Integer.MAX_VALUE) {
|
||||
appVersion += " (" + app.getBuild().asString() + ")";
|
||||
}
|
||||
|
||||
|
||||
JLabel version = new JLabel(appVersion);
|
||||
version.setFont(getProductFont().deriveFont(16f));
|
||||
version.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
version.setForeground(Gray._128);
|
||||
|
||||
|
||||
panel.add(appName);
|
||||
panel.add(version, BorderLayout.SOUTH);
|
||||
panel.setBorder(new EmptyBorder(0, 0, 20, 0));
|
||||
@@ -393,9 +396,9 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
private Font getProductFont() {
|
||||
String name = "/fonts/Roboto-Light.ttf";
|
||||
URL url = AppUIUtil.class.getResource(name);
|
||||
if (url == null) {
|
||||
Logger.getInstance(AppUIUtil.class).warn("Resource missing: " + name);
|
||||
} else {
|
||||
if (url == null) {
|
||||
Logger.getInstance(AppUIUtil.class).warn("Resource missing: " + name);
|
||||
} else {
|
||||
|
||||
try {
|
||||
InputStream is = url.openStream();
|
||||
@@ -450,7 +453,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
if (focusListOnLeft) {
|
||||
if (list != null) {
|
||||
list.requestFocus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
focusPrev(comp);
|
||||
}
|
||||
@@ -533,14 +536,15 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
if (child instanceof ActionGroup) {
|
||||
return new IconsFreeActionGroup((ActionGroup)child);
|
||||
}
|
||||
|
||||
Presentation presentation = child.getTemplatePresentation();
|
||||
|
||||
Presentation presentation = child.getTemplatePresentation();
|
||||
return new AnAction(presentation.getText(),
|
||||
presentation.getDescription(),
|
||||
null) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
child.actionPerformed(e);
|
||||
UsageTrigger.trigger("welcome.screen." + e.getActionManager().getId(child));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -558,6 +562,15 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private static Runnable createUsageTracker(final AnAction action) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UsageTrigger.trigger("welcome.screen." + ActionManager.getInstance().getId(action));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static JLabel createArrow(final ActionLink link) {
|
||||
JLabel arrow = new JLabel(AllIcons.General.Combo3);
|
||||
arrow.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
@@ -613,7 +626,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
public static void notifyFrameClosed(JFrame frame) {
|
||||
saveLocation(frame.getBounds());
|
||||
}
|
||||
|
||||
|
||||
public static class WelcomeScreenActionsPanel {
|
||||
private JPanel root;
|
||||
private JPanel actions;
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.components.OrphanGuardian;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.FilteringIterator;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
@@ -230,47 +229,16 @@ public class IJSwingUtilities extends JBSwingUtilities {
|
||||
* @param c component
|
||||
* @see javax.swing.SwingUtilities#updateComponentTreeUI
|
||||
*/
|
||||
public static void updateComponentTreeUI(Component c) {
|
||||
updateComponentTreeUI0(c);
|
||||
public static void updateComponentTreeUI(@Nullable Component c) {
|
||||
if (c == null) return;
|
||||
for (Component component : uiTraverser().postOrderTraversal(c)) {
|
||||
if (component instanceof JComponent) ((JComponent)component).updateUI();
|
||||
}
|
||||
c.invalidate();
|
||||
c.validate();
|
||||
c.repaint();
|
||||
}
|
||||
|
||||
private static final Consumer<JComponent> UI_TREE_UPDATER = new Consumer<JComponent>() {
|
||||
@Override
|
||||
public void consume(JComponent component) {
|
||||
updateComponentTreeUI0(component);
|
||||
}
|
||||
};
|
||||
|
||||
private static void updateComponentTreeUI0(Component c) {
|
||||
Component[] children = null;
|
||||
if (c instanceof JMenu) {
|
||||
children = ((JMenu)c).getMenuComponents();
|
||||
}
|
||||
else if (c instanceof Container) {
|
||||
children = ((Container)c).getComponents();
|
||||
}
|
||||
if (children != null) {
|
||||
for (Component aChildren : children) {
|
||||
updateComponentTreeUI0(aChildren);
|
||||
}
|
||||
}
|
||||
if (c instanceof JComponent) {
|
||||
JComponent jc = (JComponent)c;
|
||||
OrphanGuardian orphans = (OrphanGuardian)jc.getClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY);
|
||||
if (orphans != null) {
|
||||
orphans.iterateOrphans(UI_TREE_UPDATER);
|
||||
}
|
||||
jc.updateUI();
|
||||
JPopupMenu jpm = jc.getComponentPopupMenu();
|
||||
if (jpm != null && jpm.isVisible() && jpm.getInvoker() == jc) {
|
||||
updateComponentTreeUI(jpm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void moveMousePointerOn(Component component) {
|
||||
if (component != null && component.isShowing()) {
|
||||
UISettings settings = ApplicationManager.getApplication() == null ? null : UISettings.getInstance();
|
||||
|
||||
@@ -514,7 +514,7 @@ message.idea.restart.required=Restart {0} to activate changes in plugins?
|
||||
title.plugins=Plugins
|
||||
title.plugins.changed=Plugins Changed
|
||||
plugin.status.not.specified=(not specified)
|
||||
error.list.of.plugins.was.not.loaded=List of plugins was not loaded: {0}
|
||||
error.list.of.plugins.was.not.loaded=Unable to update the list of plugins due to the following error: {0}
|
||||
action.download.and.install.plugin=Download and Install
|
||||
action.update.plugin=Update Plugin
|
||||
error.plugin.download.failed=Plugin download failed
|
||||
|
||||
+3
@@ -146,6 +146,7 @@ public class MatcherImpl {
|
||||
visitor.matchContext(matchedNodes);
|
||||
} finally {
|
||||
matchedNodes.reset();
|
||||
matchContext.getOptions().setScope(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,6 +441,8 @@ public class MatcherImpl {
|
||||
MalformedPatternException exception = new MalformedPatternException();
|
||||
exception.initCause(e);
|
||||
throw exception;
|
||||
} finally {
|
||||
options.setScope(null);
|
||||
}
|
||||
|
||||
return sink.getMatches();
|
||||
|
||||
@@ -26,12 +26,14 @@ import java.util.HashMap;
|
||||
* @author max
|
||||
*/
|
||||
public class Conditions {
|
||||
private Conditions() {}
|
||||
private Conditions() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> Condition<T> alwaysTrue() {
|
||||
return (Condition<T>)TRUE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> Condition<T> alwaysFalse() {
|
||||
return (Condition<T>)FALSE;
|
||||
@@ -67,12 +69,23 @@ public class Conditions {
|
||||
public static <T> Condition<T> not(Condition<T> c) {
|
||||
return new Not<T>(c);
|
||||
}
|
||||
|
||||
public static <T> Condition<T> and(Condition<T> c1, Condition<T> c2) {
|
||||
return new And<T>(c1, c2);
|
||||
}
|
||||
|
||||
public static <T> Condition<T> and2(Condition<? super T> c1, Condition<? super T> c2) {
|
||||
return new And<T>(c1, c2);
|
||||
}
|
||||
|
||||
public static <T> Condition<T> or(Condition<T> c1, Condition<T> c2) {
|
||||
return new Or<T>(c1, c2);
|
||||
}
|
||||
|
||||
public static <T> Condition<T> or2(Condition<? super T> c1, Condition<? super T> c2) {
|
||||
return new Or<T>(c1, c2);
|
||||
}
|
||||
|
||||
public static <T> Condition<T> cached(Condition<T> c) {
|
||||
return new SoftRefCache<T>(c);
|
||||
}
|
||||
@@ -89,11 +102,12 @@ public class Conditions {
|
||||
return !myCondition.value(value);
|
||||
}
|
||||
}
|
||||
private static class And<T> implements Condition<T> {
|
||||
private final Condition<T> t1;
|
||||
private final Condition<T> t2;
|
||||
|
||||
public And(final Condition<T> t1, final Condition<T> t2) {
|
||||
private static class And<T> implements Condition<T> {
|
||||
private final Condition<? super T> t1;
|
||||
private final Condition<? super T> t2;
|
||||
|
||||
public And(Condition<? super T> t1, Condition<? super T> t2) {
|
||||
this.t1 = t1;
|
||||
this.t2 = t2;
|
||||
}
|
||||
@@ -103,11 +117,12 @@ public class Conditions {
|
||||
return t1.value(object) && t2.value(object);
|
||||
}
|
||||
}
|
||||
private static class Or<T> implements Condition<T> {
|
||||
private final Condition<T> t1;
|
||||
private final Condition<T> t2;
|
||||
|
||||
public Or(final Condition<T> t1, final Condition<T> t2) {
|
||||
private static class Or<T> implements Condition<T> {
|
||||
private final Condition<? super T> t1;
|
||||
private final Condition<? super T> t2;
|
||||
|
||||
public Or(Condition<? super T> t1, Condition<? super T> t2) {
|
||||
this.t1 = t1;
|
||||
this.t2 = t2;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A pruned version of com.google.common.collect.FluentIterable.
|
||||
* <p/>
|
||||
* {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a
|
||||
* chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set
|
||||
* of elements. The following types of methods are provided on {@code FluentIterable}:
|
||||
* <ul>
|
||||
* <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
|
||||
* of the current one (for example {@link #transform})
|
||||
* <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
|
||||
* array (for example {@link #toList})
|
||||
* <li>element extraction methods which facilitate the retrieval of certain elements (for example
|
||||
* {@link #last})
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <p>Here is an example that merges the lists returned by two separate database calls, transforms
|
||||
* it by invoking {@code toString()} on each element, and returns the first 10 elements as an
|
||||
* {@code List}: <pre> {@code
|
||||
* FluentIterable
|
||||
* .from(database.getClientList())
|
||||
* .filter(activeInLastMonth())
|
||||
* .transform(Functions.toStringFunction())
|
||||
* .toList();}</pre>
|
||||
* <p/>
|
||||
* <p>Anything which can be done using {@code FluentIterable} could be done in a different fashion
|
||||
* (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
|
||||
* operations significantly more concise.
|
||||
*
|
||||
* @author Marcin Mikosik
|
||||
*/
|
||||
public abstract class FluentIterable<E> implements Iterable<E> {
|
||||
// We store 'iterable' and use it instead of 'this' to allow Iterables to perform instanceof
|
||||
// checks on the _original_ iterable when FluentIterable.from is used.
|
||||
private final Iterable<E> myIterable;
|
||||
|
||||
/**
|
||||
* Constructor for use by subclasses.
|
||||
*/
|
||||
protected FluentIterable() {
|
||||
myIterable = this;
|
||||
}
|
||||
|
||||
FluentIterable(@NotNull Iterable<E> iterable) {
|
||||
myIterable = iterable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
|
||||
* is already a {@code FluentIterable}.
|
||||
*/
|
||||
public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
|
||||
return iterable instanceof FluentIterable ? (FluentIterable<E>)iterable :
|
||||
new FluentIterable<E>(iterable) {
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return iterable.iterator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fluent iterable containing {@code elements} in the specified order.
|
||||
*/
|
||||
public static <E> FluentIterable<E> of(E[] elements) {
|
||||
return from(ContainerUtil.newArrayList(elements));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this fluent iterable, with the format
|
||||
* {@code [e1, e2, ..., en]}.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return ContainerUtil.toCollection(myIterable).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this fluent iterable.
|
||||
*/
|
||||
public final int size() {
|
||||
int count = 0;
|
||||
for (E ignored : myIterable) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this fluent iterable contains any object for which
|
||||
* {@code equals(element)} is true.
|
||||
*/
|
||||
public final boolean contains(@Nullable Object element) {
|
||||
if (myIterable instanceof Collection) {
|
||||
return ((Collection)myIterable).contains(element);
|
||||
}
|
||||
for (E e : myIterable) {
|
||||
if (Comparing.equal(e, element)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
|
||||
* followed by those of {@code other}. The iterators are not polled until necessary.
|
||||
* <p/>
|
||||
* <p>The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding
|
||||
* {@code Iterator} supports it.
|
||||
*/
|
||||
public final FluentIterable<E> append(Iterable<? extends E> other) {
|
||||
return from(ContainerUtil.concat(myIterable, other));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
|
||||
* followed by {@code elements}.
|
||||
*/
|
||||
public final FluentIterable<E> append(E... elements) {
|
||||
return append(Arrays.asList(elements));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elements from this fluent iterable that satisfy a condition. The
|
||||
* resulting fluent iterable's iterator does not support {@code remove()}.
|
||||
*/
|
||||
public final FluentIterable<E> filter(final Condition<? super E> condition) {
|
||||
return from(new Iterable<E>() {
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return FilteringIterator.create(FluentIterable.this.iterator(), condition);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elements from this fluent iterable that are instances of class {@code type}.
|
||||
* @param type the type of elements desired
|
||||
*/
|
||||
public final <T> FluentIterable<T> filter(Class<T> type) {
|
||||
//noinspection unchecked
|
||||
return (FluentIterable<T>)filter(Conditions.instanceOf(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fluent iterable that applies {@code function} to each element of this
|
||||
* fluent iterable.
|
||||
* <p/>
|
||||
* <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
|
||||
* iterator does. After a successful {@code remove()} call, this fluent iterable no longer
|
||||
* contains the corresponding element.
|
||||
*/
|
||||
@NotNull
|
||||
public final <T> FluentIterable<T> transform(@NotNull final Function<? super E, T> function) {
|
||||
return from(new Iterable<T>() {
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
final Iterator<E> iterator = FluentIterable.this.iterator();
|
||||
return new Iterator<T>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return function.fun(iterator.next());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
iterator.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} containing the first element in this fluent iterable.
|
||||
* If the iterable is empty, {@code Optional.absent()} is returned.
|
||||
*/
|
||||
@Nullable
|
||||
public final E first() {
|
||||
Iterator<E> iterator = myIterable.iterator();
|
||||
return iterator.hasNext() ? iterator.next() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} containing the last element in this fluent iterable.
|
||||
* If the iterable is empty, {@code Optional.absent()} is returned.
|
||||
*/
|
||||
@Nullable
|
||||
public final E last() {
|
||||
if (myIterable instanceof List) {
|
||||
return ContainerUtil.getLastItem((List<E>)myIterable);
|
||||
}
|
||||
Iterator<E> iterator = myIterable.iterator();
|
||||
E cur = null;
|
||||
while (iterator.hasNext()) {
|
||||
cur = iterator.next();
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this fluent iterable is empty.
|
||||
*/
|
||||
public final boolean isEmpty() {
|
||||
return !myIterable.iterator().hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code List} containing all of the elements from this fluent iterable in
|
||||
* proper sequence.
|
||||
*/
|
||||
public final List<E> toList() {
|
||||
return Collections.unmodifiableList(ContainerUtil.newArrayList(myIterable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code Set} containing all of the elements from this fluent iterable with
|
||||
* duplicates removed.
|
||||
*/
|
||||
public final Set<E> toSet() {
|
||||
return Collections.unmodifiableSet(ContainerUtil.newHashSet(myIterable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code Map} for which the elements of this {@code FluentIterable} are the keys in
|
||||
* the same order, mapped to values by the given function. If this iterable contains duplicate
|
||||
* elements, the returned map will contain each distinct element once in the order it first
|
||||
* appears.
|
||||
*/
|
||||
public final <V> Map<E, V> toMap(Convertor<E, V> valueFunction) {
|
||||
return Collections.unmodifiableMap(ContainerUtil.newMapFromKeys(iterator(), valueFunction));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the elements from this fluent iterable to {@code collection}. This is equivalent to
|
||||
* calling {@code Iterables.addAll(collection, this)}.
|
||||
*
|
||||
* @param collection the collection to copy elements to
|
||||
* @return {@code collection}, for convenience
|
||||
*/
|
||||
public final <C extends Collection<? super E>> C copyInto(@NotNull C collection) {
|
||||
if (myIterable instanceof Collection) {
|
||||
collection.addAll((Collection<E>)myIterable);
|
||||
}
|
||||
else {
|
||||
for (E item : myIterable) {
|
||||
collection.add(item);
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.UnmodifiableIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A pruned version of com.google.common.collect.TreeTraverser.
|
||||
*
|
||||
* Views elements of a type {@code T} as nodes in a tree, and provides methods to traverse the trees
|
||||
* induced by this traverser.
|
||||
*
|
||||
* <p>For example, the tree
|
||||
*
|
||||
* <pre> {@code
|
||||
* h
|
||||
* / | \
|
||||
* / e \
|
||||
* d g
|
||||
* /|\ |
|
||||
* / | \ f
|
||||
* a b c }</pre>
|
||||
*
|
||||
* <p>can be iterated over in preorder (hdabcegf), postorder (abcdefgh), or breadth-first order
|
||||
* (hdegabcf).
|
||||
*
|
||||
* <p>Null nodes are strictly forbidden.
|
||||
*
|
||||
* @author Louis Wasserman
|
||||
*/
|
||||
public abstract class TreeTraverser<T> {
|
||||
/**
|
||||
* Returns the children of the specified node. Must not contain null.
|
||||
*/
|
||||
public abstract Iterable<T> children(T root);
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order
|
||||
* traversal. That is, each node's subtrees are traversed after the node itself is returned.
|
||||
*
|
||||
* <p>No guarantees are made about the behavior of the traversal when nodes change while
|
||||
* iteration is in progress or when the iterators generated by {@link #children} are advanced.
|
||||
*/
|
||||
public final FluentIterable<T> preOrderTraversal(@NotNull final T root) {
|
||||
return new FluentIterable<T>() {
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return preOrderIterator(root);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Iterator<T> preOrderIterator(@NotNull T root) {
|
||||
return new PreOrderIterator(root);
|
||||
}
|
||||
|
||||
private final class PreOrderIterator extends UnmodifiableIterator<T> {
|
||||
private final Deque<Iterator<T>> stack;
|
||||
|
||||
PreOrderIterator(@NotNull T root) {
|
||||
super(null);
|
||||
this.stack = new ArrayDeque<Iterator<T>>();
|
||||
stack.addLast(new SingletonIterator<T>(root));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !stack.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
Iterator<T> itr = stack.getLast(); // throws NSEE if empty
|
||||
T result = ObjectUtils.assertNotNull(itr.next());
|
||||
if (!itr.hasNext()) {
|
||||
stack.removeLast();
|
||||
}
|
||||
Iterator<T> childItr = children(result).iterator();
|
||||
if (childItr.hasNext()) {
|
||||
stack.addLast(childItr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable iterable over the nodes in a tree structure, using post-order
|
||||
* traversal. That is, each node's subtrees are traversed before the node itself is returned.
|
||||
*
|
||||
* <p>No guarantees are made about the behavior of the traversal when nodes change while
|
||||
* iteration is in progress or when the iterators generated by {@link #children} are advanced.
|
||||
*/
|
||||
public final FluentIterable<T> postOrderTraversal(@NotNull final T root) {
|
||||
return new FluentIterable<T>() {
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return postOrderIterator(root);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Iterator<T> postOrderIterator(@NotNull T root) {
|
||||
return new PostOrderIterator(root);
|
||||
}
|
||||
|
||||
private static final class PostOrderNode<T> {
|
||||
final T root;
|
||||
final Iterator<T> childIterator;
|
||||
|
||||
PostOrderNode(@NotNull T root, @NotNull Iterator<T> childIterator) {
|
||||
this.root = root;
|
||||
this.childIterator = childIterator;
|
||||
}
|
||||
}
|
||||
|
||||
private final class PostOrderIterator extends UnmodifiableIterator<T> {
|
||||
private final ArrayDeque<PostOrderNode<T>> stack;
|
||||
|
||||
PostOrderIterator(T root) {
|
||||
super(null);
|
||||
this.stack = new ArrayDeque<PostOrderNode<T>>();
|
||||
stack.addLast(expand(root));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !stack.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return computeNext();
|
||||
}
|
||||
|
||||
private T computeNext() {
|
||||
while (!stack.isEmpty()) {
|
||||
PostOrderNode<T> top = stack.getLast();
|
||||
if (top.childIterator.hasNext()) {
|
||||
T child = top.childIterator.next();
|
||||
stack.addLast(expand(child));
|
||||
} else {
|
||||
stack.removeLast();
|
||||
return top.root;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private PostOrderNode<T> expand(T t) {
|
||||
return new PostOrderNode<T>(t, children(t).iterator());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable iterable over the nodes in a tree structure, using breadth-first
|
||||
* traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on.
|
||||
*
|
||||
* <p>No guarantees are made about the behavior of the traversal when nodes change while
|
||||
* iteration is in progress or when the iterators generated by {@link #children} are advanced.
|
||||
*/
|
||||
public final FluentIterable<T> breadthFirstTraversal(@NotNull final T root) {
|
||||
return new FluentIterable<T>() {
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new BreadthFirstIterator(root);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final class BreadthFirstIterator extends UnmodifiableIterator<T> {
|
||||
private final Deque<T> queue;
|
||||
|
||||
BreadthFirstIterator(@NotNull T root) {
|
||||
super(null);
|
||||
this.queue = new ArrayDeque<T>();
|
||||
queue.add(root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !queue.isEmpty();
|
||||
}
|
||||
|
||||
//@Override
|
||||
public T peek() {
|
||||
return queue.element();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
T result = queue.remove();
|
||||
ContainerUtil.addAll(queue, children(result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,25 @@
|
||||
*/
|
||||
package com.intellij.util.ui;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.TreeTraverser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public class JBSwingUtilities {
|
||||
|
||||
public static final Key<Iterable<? extends Component>> NOT_IN_HIERARCHY_COMPONENTS = Key.create("NOT_IN_HIERARCHY_COMPONENTS");
|
||||
|
||||
/**
|
||||
* Replaces SwingUtilities#isLeftMouseButton() for consistency with other button-related methods
|
||||
*
|
||||
@@ -50,4 +62,32 @@ public class JBSwingUtilities {
|
||||
public static boolean isRightMouseButton(MouseEvent anEvent) {
|
||||
return (anEvent.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) > 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TreeTraverser<Component> uiTraverser() {
|
||||
return new TreeTraverser<Component>() {
|
||||
@Override
|
||||
public Iterable<Component> children(Component c) {
|
||||
Iterable<Component> result = ContainerUtil.emptyIterable();
|
||||
if (c instanceof JMenu) {
|
||||
result = Arrays.asList(((JMenu)c).getMenuComponents());
|
||||
}
|
||||
else if (c instanceof Container) {
|
||||
result = Arrays.asList(((Container)c).getComponents());
|
||||
}
|
||||
if (c instanceof JComponent) {
|
||||
JComponent jc = (JComponent)c;
|
||||
Iterable<? extends Component> orphans = UIUtil.getClientProperty(jc, NOT_IN_HIERARCHY_COMPONENTS);
|
||||
if (orphans != null) {
|
||||
result = ContainerUtil.concat(result, orphans);
|
||||
}
|
||||
JPopupMenu jpm = jc.getComponentPopupMenu();
|
||||
if (jpm != null && jpm.isVisible() && jpm.getInvoker() == jc) {
|
||||
result = ContainerUtil.concat(result, Collections.singletonList(jpm));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,6 +345,10 @@ public class UIUtil {
|
||||
return (T)component.getClientProperty(key);
|
||||
}
|
||||
|
||||
public static <T> void putClientProperty(@NotNull JComponent component, @NotNull Key<T> key, T value) {
|
||||
component.putClientProperty(key, value);
|
||||
}
|
||||
|
||||
public static String getHtmlBody(String text) {
|
||||
int htmlIndex = 6 + text.indexOf("<html>");
|
||||
if (htmlIndex < 6) {
|
||||
|
||||
@@ -440,7 +440,9 @@ public abstract class AbstractVcs<ComList extends CommittedChangeList> extends S
|
||||
}
|
||||
|
||||
public interface RootsConvertor {
|
||||
List<VirtualFile> convertRoots(List<VirtualFile> result);
|
||||
|
||||
@NotNull
|
||||
List<VirtualFile> convertRoots(@NotNull List<VirtualFile> result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -273,6 +273,7 @@ public class NewMappings {
|
||||
return FileUtil.startsWith(systemIndependentPath, mapping.systemIndependentPath());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<VirtualFile> getMappingsAsFilesUnderVcs(@NotNull AbstractVcs vcs) {
|
||||
final List<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
final String vcsName = vcs.getName();
|
||||
|
||||
@@ -354,7 +354,8 @@ public class CvsVcs2 extends AbstractVcs<CvsChangeList> implements TransactionPr
|
||||
@Override
|
||||
public RootsConvertor getCustomConvertor() {
|
||||
return new RootsConvertor() {
|
||||
public List<VirtualFile> convertRoots(List<VirtualFile> result) {
|
||||
@NotNull
|
||||
public List<VirtualFile> convertRoots(@NotNull List<VirtualFile> result) {
|
||||
return FindAllRootsHelper.findVersionedUnder(result);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
@@ -44,8 +45,9 @@ public class HgRootsHandler implements AbstractVcs.RootsConvertor {
|
||||
return ServiceManager.getService(project, HgRootsHandler.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<VirtualFile> convertRoots(List<VirtualFile> original) {
|
||||
public List<VirtualFile> convertRoots(@NotNull List<VirtualFile> original) {
|
||||
final Set<VirtualFile> result = new THashSet<VirtualFile>(original.size());
|
||||
for (VirtualFile vf : original) {
|
||||
final VirtualFile root = convertRoot(vf);
|
||||
|
||||
@@ -191,8 +191,9 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState
|
||||
}
|
||||
}
|
||||
|
||||
public List<VirtualFile> convertRoots(final List<VirtualFile> result) {
|
||||
if (ThreadLocalDefendedInvoker.isInside()) return result;
|
||||
@NotNull
|
||||
public List<VirtualFile> convertRoots(@NotNull List<VirtualFile> result) {
|
||||
if (ThreadLocalDefendedInvoker.isInside()) return ContainerUtil.newArrayList(result);
|
||||
|
||||
synchronized (myMonitor) {
|
||||
final List<VirtualFile> cachedRoots = myMoreRealMapping.getUnderVcsRoots();
|
||||
@@ -200,11 +201,8 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState
|
||||
if (! lonelyRoots.isEmpty()) {
|
||||
myChecker.reportNoRoots(lonelyRoots);
|
||||
}
|
||||
if (cachedRoots.isEmpty()) {
|
||||
// todo +-
|
||||
return result;
|
||||
}
|
||||
return cachedRoots;
|
||||
|
||||
return ContainerUtil.newArrayList(cachedRoots.isEmpty() ? result : cachedRoots);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,6 @@ jira.failure.captcha=Login failed. Enter captcha in web-interface.
|
||||
youtrack.default.query=for: me sort by: updated #Unresolved
|
||||
|
||||
## Bugzilla
|
||||
bugzilla.failure.malformed.response=Cannot decode server response. Check that XMLRPC plugin is enabled.
|
||||
bugzilla.failure.malformed.response=Cannot decode server response. Check that XML-RPC plugin is enabled.
|
||||
bugzilla.failure.no.version=Cannot find Bugzilla version. Check that URL ends with "xmlrpc.cgi".
|
||||
|
||||
|
||||
@@ -346,7 +346,8 @@ public class BugzillaRepository extends BaseRepositoryImpl {
|
||||
return (T)new XmlRpcClient(getUrl()).execute(new XmlRpcRequest(myMethodName, parameters), myTransport);
|
||||
}
|
||||
catch (XmlRpcClientException e) {
|
||||
if (e.getMessage().contains("Error decoding XML-RPC response")) {
|
||||
// Unfortunately there is no standard error code to identify this kind of error in portable way
|
||||
if (e.getMessage().equals("Error decoding XML-RPC response")) {
|
||||
throw new RequestFailedException(TaskBundle.message("bugzilla.failure.malformed.response"), e);
|
||||
}
|
||||
throw e;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
@@ -46,9 +46,9 @@ def check_importable_path(path):
|
||||
try:
|
||||
import_file(path)
|
||||
except:
|
||||
failed("File contains syntax errors", test_file_importable.__name__)
|
||||
failed("File contains syntax errors", test_file_importable.func_name)
|
||||
return
|
||||
passed(test_file_importable.__name__)
|
||||
passed(test_file_importable.func_name)
|
||||
|
||||
|
||||
def import_file(path):
|
||||
@@ -126,11 +126,11 @@ def test_text_equals(text, error_text):
|
||||
failed(error_text)
|
||||
|
||||
|
||||
def test_window_text_deleted(error_text="Don't just delete task text"):
|
||||
def test_answer_placeholders_text_deleted(error_text="Don't just delete task text"):
|
||||
"""
|
||||
Checks that task windows are not empty
|
||||
Checks that all answer placeholders are not empty
|
||||
"""
|
||||
windows = get_task_windows()
|
||||
windows = get_answer_placeholders()
|
||||
|
||||
for window in windows:
|
||||
if len(window) == 0:
|
||||
@@ -153,9 +153,9 @@ def passed(name=None):
|
||||
print("#educational_plugin " + name + " test OK")
|
||||
|
||||
|
||||
def get_task_windows(file_name=None):
|
||||
def get_answer_placeholders(file_name=None):
|
||||
"""
|
||||
Returns all task windows
|
||||
Returns all answer placeholders text
|
||||
"""
|
||||
prefix = "#educational_plugin_window = "
|
||||
import os
|
||||
@@ -198,4 +198,4 @@ def run_common_tests(error_text="Please, reload file and try again"):
|
||||
test_file_importable()
|
||||
test_is_not_empty()
|
||||
test_is_initial_text(error_text)
|
||||
test_window_text_deleted(error_text)
|
||||
test_answer_placeholders_text_deleted(error_text)
|
||||
@@ -1,10 +1,10 @@
|
||||
from test_helper import run_common_tests, failed, passed, get_task_windows
|
||||
from test_helper import run_common_tests, failed, passed, get_answer_placeholders
|
||||
|
||||
|
||||
def test_task_windows():
|
||||
windows = get_task_windows()
|
||||
window = windows[0]
|
||||
if window == "": # TODO: your condition here
|
||||
def test_answer_placeholders():
|
||||
placeholders = get_answer_placeholders()
|
||||
placeholder = placeholders[0]
|
||||
if placeholder == "": # TODO: your condition here
|
||||
passed()
|
||||
else:
|
||||
failed()
|
||||
@@ -12,6 +12,6 @@ def test_task_windows():
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_common_tests()
|
||||
# test_task_windows() # TODO: uncomment test call
|
||||
# test_answer_placeholders() # TODO: uncomment test call
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class CCEditorFactoryListener implements EditorFactoryListener {
|
||||
|
||||
@Override
|
||||
public void handle(ReadOnlyFragmentModificationException e) {
|
||||
HintManager.getInstance().showErrorHint(myEditor, "Delete task window before editing its borders");
|
||||
HintManager.getInstance().showErrorHint(myEditor, "Delete answer placeholder before editing its borders");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ public class CCAddTaskWindow extends DumbAwareAction {
|
||||
private static final Logger LOG = Logger.getInstance(CCAddTaskWindow.class);
|
||||
|
||||
public CCAddTaskWindow() {
|
||||
super("Add Problem to Solve", "Add problem to solve", null);
|
||||
super("Add Answer Placeholder", "Add answer placeholder", null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ public class CCCreateCourseArchive extends DumbAwareAction {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
String name = pathname.getName();
|
||||
return !name.contains(".answer") && !name.contains("__pycache__") && !name.contains("_windows");
|
||||
return !name.contains(".answer") && !name.contains("__pycache__") && !name.contains("_windows") && !name.contains(".pyc");
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ public class CCDeleteTaskWindow extends CCTaskWindowAction {
|
||||
private static final Logger LOG = Logger.getInstance(CCDeleteTaskWindow.class);
|
||||
|
||||
public CCDeleteTaskWindow() {
|
||||
super("Delete Problem","Delete problem", null);
|
||||
super("Delete Answer Placeholder","Delete answer placeholder", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowDialog;
|
||||
public class CCShowTaskWindowDetails extends CCTaskWindowAction {
|
||||
|
||||
public CCShowTaskWindowDetails() {
|
||||
super("Show Problem Details", "Show problem details", null);
|
||||
super("Edit Answer Placeholder", "Edit answer placeholder", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.io.*;
|
||||
|
||||
public class CreateTaskWindowDialog extends DialogWrapper {
|
||||
|
||||
public static final String TITLE = "Add Problem to Solve";
|
||||
public static final String TITLE = "Add Answer Placeholder";
|
||||
private static final Logger LOG = Logger.getInstance(CreateTaskWindowDialog.class.getName());
|
||||
private final TaskWindow myTaskWindow;
|
||||
private final CreateTaskWindowPanel myPanel;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<id>com.jetbrains.python.edu.learn-python</id>
|
||||
<name>Educational plugin for PyCharm</name>
|
||||
<version>1.1</version>
|
||||
<vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
|
||||
|
||||
<description><![CDATA[
|
||||
Educational plugin for students. This plugin allows to learn Python
|
||||
@@ -41,11 +40,11 @@
|
||||
<action id="CheckAction" class="com.jetbrains.python.edu.actions.StudyCheckAction" text="Check Task"
|
||||
description="Check current task">
|
||||
</action>
|
||||
<action id="PrevWindowAction" class="com.jetbrains.python.edu.actions.StudyPrevWindowAction" text="Previous Task Window"
|
||||
description="Navigate to previous task window">
|
||||
<action id="PrevWindowAction" class="com.jetbrains.python.edu.actions.StudyPrevWindowAction" text="Previous Answer Placeholder"
|
||||
description="Navigate to the previous answer placeholder">
|
||||
</action>
|
||||
<action id="NextWindow" class="com.jetbrains.python.edu.actions.StudyNextWindowAction" text="Next Task Window"
|
||||
description="Navigate to next task window">
|
||||
<action id="NextWindow" class="com.jetbrains.python.edu.actions.StudyNextWindowAction" text="Next Answer Placeholder"
|
||||
description="Navigate to the next answer holder">
|
||||
</action>
|
||||
<action id="PreviousTaskAction" class="com.jetbrains.python.edu.actions.StudyPreviousStudyTaskAction" text="Previous Task"
|
||||
description="Navigate to previous task"/>
|
||||
@@ -55,8 +54,8 @@
|
||||
description="Refresh current task"/>
|
||||
<action id="WatchInputAction" class="com.jetbrains.python.edu.actions.StudyEditInputAction" text="Watch Test Input"
|
||||
description="Watch test input "/>
|
||||
<action id="ShowHintAction" class="com.jetbrains.python.edu.actions.StudyShowHintAction" text="Show Hint for Task Window"
|
||||
description="Show hint for task window"/>
|
||||
<action id="ShowHintAction" class="com.jetbrains.python.edu.actions.StudyShowHintAction" text="Show Hint for Answer Placeholder"
|
||||
description="Show hint for answer placeholder"/>
|
||||
<action id="StudyRunAction" class="com.jetbrains.python.edu.actions.StudyRunAction" text="Run File With Tests"
|
||||
description="Run your code with tests"/>
|
||||
<action id="WelcomeScreen.PythonIntro" class="com.jetbrains.python.edu.actions.StudyIntroductionCourseAction" icon="StudyIcons.EducationalProjectType">
|
||||
|
||||
Binary file not shown.
+10
-2
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
|
||||
@@ -188,7 +189,6 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
|
||||
final VirtualFile taskDir = firstTask.getTaskDir(myProject);
|
||||
if (taskDir == null) return;
|
||||
final Map<String, TaskFile> taskFiles = firstTask.getTaskFiles();
|
||||
|
||||
VirtualFile activeVirtualFile = null;
|
||||
for (Map.Entry<String, TaskFile> entry : taskFiles.entrySet()) {
|
||||
final String name = entry.getKey();
|
||||
@@ -204,8 +204,16 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
|
||||
if (activeVirtualFile != null) {
|
||||
final PsiFile file = PsiManager.getInstance(myProject).findFile(activeVirtualFile);
|
||||
ProjectView.getInstance(project).select(file, activeVirtualFile, true);
|
||||
initialized[0] = true;
|
||||
} else {
|
||||
String first = StudyUtils.getFirst(taskFiles.keySet());
|
||||
if (first != null) {
|
||||
NewVirtualFile firstFile = ((VirtualDirectoryImpl)taskDir).refreshAndFindChild(first);
|
||||
if (firstFile != null) {
|
||||
FileEditorManager.getInstance(project).openFile(firstFile, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
initialized[0] = true;
|
||||
}
|
||||
}, ModalityState.current(), new Condition() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ class StudyEditorFactoryListener implements EditorFactoryListener {
|
||||
|
||||
@Override
|
||||
public void handle(ReadOnlyFragmentModificationException e) {
|
||||
HintManager.getInstance().showErrorHint(myEditor, "It's not allowed to delete task windows");
|
||||
HintManager.getInstance().showErrorHint(myEditor, "It's not allowed to delete answer placeholders");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter {
|
||||
UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f);
|
||||
|
||||
painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180));
|
||||
addAction(painter, "Navigate to the next task window", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true);
|
||||
addAction(painter, "Navigate to the next answer placeholder", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true);
|
||||
String shortcut1 = getShortcutText(StudyPrevWindowAction.ACTION_ID, StudyPrevWindowAction.SHORTCUT, false, false);
|
||||
String shortcut2 = getShortcutText(StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT, false, false);
|
||||
String text = "Navigate between task windows with " + shortcut1 +
|
||||
String text = "Navigate between answer placeholders with " + shortcut1 +
|
||||
" and " + shortcut2;
|
||||
painter.appendLine(text).smaller().withBullet();
|
||||
shortcut1 = getShortcutText(StudyPreviousStudyTaskAction.ACTION_ID, StudyPreviousStudyTaskAction.SHORTCUT, false, false);
|
||||
@@ -44,7 +44,7 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter {
|
||||
painter.appendLine("Navigate between tasks with " + shortcut1 + " and " + shortcut2).smaller().withBullet();
|
||||
addAction(painter, "Reset current task file", StudyRefreshTaskFileAction.ACTION_ID, StudyRefreshTaskFileAction.SHORTCUT, false);
|
||||
addAction(painter, "Check task", StudyCheckAction.ACTION_ID, StudyCheckAction.SHORTCUT, false);
|
||||
addAction(painter, "Get hint for the task window", StudyShowHintAction.ACTION_ID, StudyShowHintAction.SHORTCUT, false);
|
||||
addAction(painter, "Get hint for the answer placeholder", StudyShowHintAction.ACTION_ID, StudyShowHintAction.SHORTCUT, false);
|
||||
painter.appendLine("To see your progress open the 'Course Description' panel").smaller().withBullet();
|
||||
painter.draw(g, new PairFunction<Integer, Integer, Couple<Integer>>() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ public class StudyNextWindowAction extends StudyWindowNavigationAction {
|
||||
public static final String SHORTCUT2 = "ctrl pressed ENTER";
|
||||
|
||||
public StudyNextWindowAction() {
|
||||
super("NextWindowAction", "Select next window", AllIcons.Actions.Forward);
|
||||
super("Navigate to the Next Answer Placeholder", "Navigate to the next answer placeholder", AllIcons.Actions.Forward);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ public class StudyPrevWindowAction extends StudyWindowNavigationAction {
|
||||
public static final String SHORTCUT = "ctrl shift pressed COMMA";
|
||||
|
||||
public StudyPrevWindowAction() {
|
||||
super("PrevWindowAction", "Select previous window", StudyIcons.Prev);
|
||||
super("Navigate to the Previous Answer Placeholder", "Navigate to the previous answer placeholder", StudyIcons.Prev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ import java.io.File;
|
||||
public class StudyShowHintAction extends DumbAwareAction {
|
||||
public static final String ACTION_ID = "ShowHintAction";
|
||||
public static final String SHORTCUT = "ctrl pressed 7";
|
||||
public static final String OUTSIDE_TASK_WINDOW_MESSAGE = "Put caret to the task window to get hint.";
|
||||
public static final String HINT_NOT_AVAILABLE = "There is no hint for this task window";
|
||||
public static final String OUTSIDE_TASK_WINDOW_MESSAGE = "Put caret to answer placeholder to get hint";
|
||||
public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder";
|
||||
|
||||
public StudyShowHintAction() {
|
||||
super("Show hint", "Show hint", StudyIcons.ShowHint);
|
||||
|
||||
+15
-6
@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
|
||||
public class StudyDirectoryNode extends PsiDirectoryNode {
|
||||
private final PsiDirectory myValue;
|
||||
@@ -144,15 +144,24 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
|
||||
FileEditorManager.getInstance(myProject).closeFile(openFile);
|
||||
}
|
||||
VirtualFile child = null;
|
||||
Set<String> fileNames = task.getTaskFiles().keySet();
|
||||
for (String name : fileNames) {
|
||||
child = taskDir.findChild(name);
|
||||
if (child != null) {
|
||||
FileEditorManager.getInstance(myProject).openFile(child, true);
|
||||
Map<String, TaskFile> taskFiles = task.getTaskFiles();
|
||||
for (Map.Entry<String, TaskFile> entry: taskFiles.entrySet()) {
|
||||
VirtualFile file = taskDir.findChild(entry.getKey());
|
||||
if (file != null) {
|
||||
FileEditorManager.getInstance(myProject).openFile(file, true);
|
||||
}
|
||||
if (!entry.getValue().getTaskWindows().isEmpty()) {
|
||||
child = file;
|
||||
}
|
||||
}
|
||||
if (child != null) {
|
||||
ProjectView.getInstance(myProject).select(child, child, false);
|
||||
FileEditorManager.getInstance(myProject).openFile(child, true);
|
||||
} else {
|
||||
VirtualFile[] children = taskDir.getChildren();
|
||||
if (children.length > 0) {
|
||||
ProjectView.getInstance(myProject).select(children[0], children[0], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import sys
|
||||
from import_hook import import_hook_manager
|
||||
|
||||
backends = {'tk': 'TkAgg',
|
||||
'gtk': 'GTKAgg',
|
||||
@@ -57,6 +56,16 @@ def patch_use(interpreter):
|
||||
setattr(matplotlib, "use", patched_use)
|
||||
|
||||
|
||||
def patch_is_interactive():
|
||||
""" Patch matplotlib function 'use' """
|
||||
matplotlib = sys.modules['matplotlib']
|
||||
def patched_is_interactive():
|
||||
return matplotlib.rcParams['interactive']
|
||||
|
||||
setattr(matplotlib, "real_is_interactive", getattr(matplotlib, "is_interactive"))
|
||||
setattr(matplotlib, "is_interactive", patched_is_interactive)
|
||||
|
||||
|
||||
def activate_matplotlib(interpreter):
|
||||
"""Set interactive to True for interactive backends."""
|
||||
def activate_matplotlib_inner():
|
||||
@@ -73,13 +82,10 @@ def activate_matplotlib(interpreter):
|
||||
sys.stdout.write("Backend %s is non-interactive backend. Turning interactive mode off.\n" % backend)
|
||||
matplotlib.interactive(False)
|
||||
patch_use(interpreter)
|
||||
patch_is_interactive()
|
||||
return activate_matplotlib_inner
|
||||
|
||||
|
||||
def init_matplotlib(interpreter):
|
||||
import_hook_manager.add_module_name("matplotlib", activate_matplotlib(interpreter))
|
||||
|
||||
|
||||
def flag_calls(func):
|
||||
"""Wrap a function to detect and flag when it gets called.
|
||||
|
||||
@@ -116,17 +122,9 @@ def activate_pylab():
|
||||
pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
|
||||
|
||||
|
||||
def init_pylab():
|
||||
import_hook_manager.add_module_name("pylab", activate_pylab)
|
||||
|
||||
|
||||
def activate_pyplot():
|
||||
pyplot = sys.modules['matplotlib.pyplot']
|
||||
pyplot.show._needmain = False
|
||||
# We need to detect at runtime whether show() is called by the user.
|
||||
# For this, we wrap it into a decorator which adds a 'called' flag.
|
||||
pyplot.draw_if_interactive = flag_calls(pyplot.draw_if_interactive)
|
||||
|
||||
|
||||
def init_pyplot():
|
||||
import_hook_manager.add_module_name("pyplot", activate_pyplot)
|
||||
@@ -171,10 +171,11 @@ def process_exec_queue(interpreter):
|
||||
|
||||
set_return_control_callback(return_control)
|
||||
|
||||
from pydev_ipython.matplotlibtools import init_matplotlib, init_pylab, init_pyplot
|
||||
init_matplotlib(interpreter)
|
||||
init_pylab()
|
||||
init_pyplot()
|
||||
from pydev_import_hook import import_hook_manager
|
||||
from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot
|
||||
import_hook_manager.add_module_name("matplotlib", activate_matplotlib(interpreter))
|
||||
import_hook_manager.add_module_name("pylab", activate_pylab)
|
||||
import_hook_manager.add_module_name("pyplot", activate_pyplot)
|
||||
|
||||
while 1:
|
||||
# Running the request may have changed the inputhook in use
|
||||
|
||||
@@ -20,47 +20,50 @@ import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import com.jetbrains.python.testing.pytest.PyTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* User : ktisha
|
||||
*/
|
||||
public class PyPep8NamingInspection extends PyInspection {
|
||||
private static final Pattern LOWERCASE_REGEX = Pattern.compile("[_\\p{javaLowerCase}][_\\p{javaLowerCase}0-9]*");
|
||||
private static final Pattern UPPERCASE_REGEX = Pattern.compile("[_\\p{javaUpperCase}][_\\p{javaUpperCase}0-9]*");
|
||||
private static final Pattern MIXEDCASE_REGEX = Pattern.compile("_?[\\p{javaUpperCase}][\\p{javaLowerCase}\\p{javaUpperCase}0-9]*");
|
||||
|
||||
public boolean ignoreOverriddenFunctions = true;
|
||||
public boolean ignoreTestFunctions = false;
|
||||
private static Pattern LOWERCASE_REGEX = Pattern.compile("[_\\p{javaLowerCase}][_\\p{javaLowerCase}0-9]*");
|
||||
private static Pattern UPPERCASE_REGEX = Pattern.compile("[_\\p{javaUpperCase}][_\\p{javaUpperCase}0-9]*");
|
||||
private static Pattern MIXEDCASE_REGEX = Pattern.compile("_?[\\p{javaUpperCase}][\\p{javaLowerCase}\\p{javaUpperCase}0-9]*");
|
||||
public boolean ignoreDescendantsOfStandardClasses = false;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
boolean isOnTheFly,
|
||||
@NotNull LocalInspectionToolSession session) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode())
|
||||
ignoreTestFunctions = true;
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
ignoreDescendantsOfStandardClasses = true;
|
||||
}
|
||||
return new Visitor(holder, session);
|
||||
}
|
||||
|
||||
public class Visitor extends PyInspectionVisitor {
|
||||
private final Map<PyFunction, Boolean> myHasSupers = new HashMap<PyFunction, Boolean>();
|
||||
|
||||
public Visitor(@NotNull final ProblemsHolder holder, LocalInspectionToolSession session) {
|
||||
super(holder, session);
|
||||
}
|
||||
@@ -95,22 +98,42 @@ public class PyPep8NamingInspection extends PyInspection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(PyFunction node) {
|
||||
final PyClass containingClass = node.getContainingClass();
|
||||
if (hasSupers(node) && ignoreOverriddenFunctions) return;
|
||||
if(containingClass != null && PyTestUtil.isPyTestClass(containingClass) && ignoreTestFunctions) return;
|
||||
final String name = node.getName();
|
||||
public void visitPyFunction(PyFunction function) {
|
||||
final PyClass containingClass = function.getContainingClass();
|
||||
if (ignoreOverriddenFunctions && isOverriddenMethod(function)) return;
|
||||
final String name = function.getName();
|
||||
if (name == null) return;
|
||||
if (containingClass != null && name.startsWith("__") && name.endsWith("__")) {
|
||||
if (containingClass != null && PyUtil.isSpecialName(name)) {
|
||||
return;
|
||||
}
|
||||
if (containingClass != null && ignoreDescendantsOfStandardClasses && isStandardClassDescendant(containingClass)) {
|
||||
return;
|
||||
}
|
||||
if (!LOWERCASE_REGEX.matcher(name).matches()) {
|
||||
final ASTNode nameNode = node.getNameNode();
|
||||
final ASTNode nameNode = function.getNameNode();
|
||||
if (nameNode != null)
|
||||
registerProblem(nameNode.getPsi(), "Function name should be lowercase", new PyRenameElementQuickFix());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOverriddenMethod(@NotNull PyFunction function) {
|
||||
return PySuperMethodsSearch.search(function).findFirst() != null;
|
||||
}
|
||||
|
||||
private boolean isStandardClassDescendant(@NotNull final PyClass cls) {
|
||||
if (PyTestUtil.isPyTestClass(cls)) {
|
||||
return true;
|
||||
}
|
||||
return ContainerUtil.exists(cls.getAncestorClasses(myTypeEvalContext), new Condition<PyClass>() {
|
||||
@Override
|
||||
public boolean value(PyClass ancestor) {
|
||||
final PsiFile ancestorsModule = ancestor.getContainingFile();
|
||||
final Sdk sdk = PyBuiltinCache.findSdkForFile(ancestorsModule);
|
||||
return PythonSdkType.isStdLib(ancestorsModule.getVirtualFile(), sdk) && !PyBuiltinCache.getInstance(cls).isBuiltin(ancestor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyClass(PyClass node) {
|
||||
final String name = node.getName();
|
||||
@@ -147,16 +170,6 @@ public class PyPep8NamingInspection extends PyInspection {
|
||||
registerProblem(node.getAsNameElement(), "CamelCase variable imported as constant", new PyRenameElementQuickFix());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasSupers(@NotNull PyFunction function) {
|
||||
final Boolean cached = myHasSupers.get(function);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
final boolean result = PySuperMethodsSearch.search(function).findFirst() != null;
|
||||
myHasSupers.put(function, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -164,7 +177,7 @@ public class PyPep8NamingInspection extends PyInspection {
|
||||
public JComponent createOptionsPanel() {
|
||||
MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
|
||||
panel.addCheckbox("Ignore overridden functions", "ignoreOverriddenFunctions");
|
||||
panel.addCheckbox("Ignore test functions", "ignoreTestFunctions");
|
||||
panel.addCheckbox("Ignore descendants of standard classes", "ignoreDescendantsOfStandardClasses");
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.psi.search;
|
||||
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -186,6 +187,10 @@ public class PyProjectScopeBuilder extends ProjectScopeBuilderImpl {
|
||||
file.findChild("xml") != null && file.findChild("email") != null) {
|
||||
return file;
|
||||
}
|
||||
// Mock SDK does not have aforementioned modules
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() && file.getName().equals("Lib")) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -15,23 +15,26 @@
|
||||
*/
|
||||
package com.jetbrains.python.testing.pytest;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyStatement;
|
||||
import com.jetbrains.python.psi.types.PyClassLikeType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* User: catherine
|
||||
*/
|
||||
public class PyTestUtil {
|
||||
private static final HashSet<String> PYTHON_TEST_QUALIFIED_CLASSES = Sets.newHashSet("unittest.TestCase", "unittest.case.TestCase");
|
||||
private static final Set<String> PYTHON_TEST_QUALIFIED_CLASSES = ImmutableSet.of("unittest.TestCase", "unittest.case.TestCase");
|
||||
|
||||
public static List<PyStatement> getPyTestCasesFromFile(PsiFileSystemItem file) {
|
||||
List<PyStatement> result = Lists.newArrayList();
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import collections
|
||||
|
||||
class MyDict(collections.OrderedDict):
|
||||
def getLast(self):
|
||||
if self:
|
||||
return list(self.values)[-1]
|
||||
raise ValueError()
|
||||
@@ -65,6 +65,11 @@ public class PyPep8NamingInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-13537
|
||||
public void testDescendantOfStandardClass() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testTest() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
package com.intellij.xml.breadcrumbs;
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions;
|
||||
import com.intellij.codeInsight.daemon.impl.tagTreeHighlighting.XmlTagTreeHighlightingUtil;
|
||||
import com.intellij.codeInsight.highlighting.HighlightManager;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.lang.Language;
|
||||
@@ -25,10 +27,14 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorFontType;
|
||||
import com.intellij.openapi.editor.event.CaretAdapter;
|
||||
import com.intellij.openapi.editor.event.CaretEvent;
|
||||
import com.intellij.openapi.editor.event.CaretListener;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -52,10 +58,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
@@ -64,6 +67,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener<Breadcrumb
|
||||
private final BreadcrumbsComponent<BreadcrumbsPsiItem> myComponent;
|
||||
private final Project myProject;
|
||||
private Editor myEditor;
|
||||
private Collection<RangeHighlighter> myHighlighed;
|
||||
private final VirtualFile myFile;
|
||||
private boolean myUserCaretChange;
|
||||
private final MergingUpdateQueue myQueue;
|
||||
@@ -383,6 +387,27 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener<Breadcrumb
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemHovered(@Nullable BreadcrumbsPsiItem item) {
|
||||
if (myHighlighed != null) {
|
||||
for (RangeHighlighter highlighter : myHighlighed) {
|
||||
HighlightManager.getInstance(myProject).removeSegmentHighlighter(myEditor, highlighter);
|
||||
}
|
||||
myHighlighed = null;
|
||||
}
|
||||
if (item != null) {
|
||||
final TextRange range = item.getPsiElement().getTextRange();
|
||||
final TextAttributes attributes = new TextAttributes();
|
||||
final CrumbPresentation p = item.getPresentation();
|
||||
final Color color = p != null ? p.getBackgroundColor(false, false, false) : BreadcrumbsComponent.ButtonSettings.DEFAULT_BG_COLOR;
|
||||
final Color background = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.CARET_ROW_COLOR);
|
||||
attributes.setBackgroundColor(XmlTagTreeHighlightingUtil.makeTransparent(color, background, 0.3));
|
||||
myHighlighed = new ArrayList<RangeHighlighter>(1);
|
||||
HighlightManager.getInstance(myProject).addRangeHighlight(myEditor, range.getStartOffset(), range.getEndOffset(),
|
||||
attributes, true, true, myHighlighed);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BreadcrumbsXmlWrapper getBreadcrumbsComponent(@NotNull Editor editor) {
|
||||
return editor.getUserData(BREADCRUMBS_COMPONENT_KEY);
|
||||
|
||||
@@ -121,6 +121,9 @@ public class BreadcrumbsComponent<T extends BreadcrumbsItem> extends JComponent
|
||||
}
|
||||
|
||||
myHovered = crumb;
|
||||
for (BreadcrumbsItemListener listener : myListeners) {
|
||||
listener.itemHovered(myHovered != null ? myHovered.myItem : null);
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
package com.intellij.xml.breadcrumbs;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
*/
|
||||
public interface BreadcrumbsItemListener<T extends BreadcrumbsItem> {
|
||||
|
||||
void itemSelected(@NotNull final T item, final int modifiers);
|
||||
|
||||
void itemHovered(@Nullable final T item);
|
||||
}
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ import java.util.Set;
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class XmlTagTreeHighlightingUtil {
|
||||
public class XmlTagTreeHighlightingUtil {
|
||||
private XmlTagTreeHighlightingUtil() {
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class XmlTagTreeHighlightingUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
static Color makeTransparent(@NotNull Color color, @NotNull Color backgroundColor, double transparency) {
|
||||
public static Color makeTransparent(@NotNull Color color, @NotNull Color backgroundColor, double transparency) {
|
||||
int r = makeTransparent(transparency, color.getRed(), backgroundColor.getRed());
|
||||
int g = makeTransparent(transparency, color.getGreen(), backgroundColor.getGreen());
|
||||
int b = makeTransparent(transparency, color.getBlue(), backgroundColor.getBlue());
|
||||
|
||||
Reference in New Issue
Block a user