mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote branch 'origin/master'
This commit is contained in:
@@ -268,7 +268,7 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
continue;
|
||||
}
|
||||
final CompilerWorkspaceConfiguration config = CompilerWorkspaceConfiguration.getInstance(project);
|
||||
if (!config.USE_COMPILE_SERVER || !config.MAKE_PROJECT_ON_SAVE) {
|
||||
if (!config.useCompileServer() || !config.MAKE_PROJECT_ON_SAVE) {
|
||||
continue;
|
||||
}
|
||||
final RequestFuture future = submitCompilationTask(
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.compiler.options;
|
||||
|
||||
import com.intellij.compiler.*;
|
||||
import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompilerBundle;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
@@ -47,9 +48,9 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
|
||||
|
||||
public CompilerUIConfigurable(final Project project) {
|
||||
myProject = project;
|
||||
final boolean isEnabled = Registry.is("compiler.server.enabled");
|
||||
myCbUseCompileServer.setVisible(isEnabled);
|
||||
myCbMakeProjectOnSave.setVisible(isEnabled);
|
||||
final boolean isServerOptionEnabled = Registry.is("compiler.server.enabled") || ApplicationManager.getApplication().isInternal();
|
||||
myCbUseCompileServer.setVisible(isServerOptionEnabled);
|
||||
myCbMakeProjectOnSave.setVisible(isServerOptionEnabled);
|
||||
|
||||
myPatternLegendLabel.setText("<html>" +
|
||||
"Use <b>;</b> to separate patterns and <b>!</b> to negate a pattern. " +
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.intellij.compiler;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
@@ -57,6 +58,6 @@ public class CompilerWorkspaceConfiguration implements PersistentStateComponent<
|
||||
}
|
||||
|
||||
public boolean useCompileServer() {
|
||||
return USE_COMPILE_SERVER && Registry.is("compiler.server.enabled");
|
||||
return USE_COMPILE_SERVER && (Registry.is("compiler.server.enabled") || ApplicationManager.getApplication().isInternal());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,8 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: db
|
||||
* Date: 26.07.11
|
||||
* Time: 0:34
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* @author db
|
||||
* @since 26.07.11
|
||||
*/
|
||||
public abstract class IncrementalTestCase extends TestCase {
|
||||
private static class RootStripper {
|
||||
@@ -82,59 +79,57 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
Logger.setFactory(new Logger.Factory() {
|
||||
@Override
|
||||
public Logger getLoggerInstance(String category) {
|
||||
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category);
|
||||
|
||||
final boolean affectedLogger = category.equals("#org.jetbrains.jps.incremental.java.JavaBuilder") ||
|
||||
category.equals("#org.jetbrains.jps.incremental.IncProjectBuilder");
|
||||
private static class MyFactory implements Logger.Factory {
|
||||
@Override
|
||||
public Logger getLoggerInstance(String category) {
|
||||
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category);
|
||||
|
||||
return new Logger() {
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return affectedLogger;
|
||||
final boolean affectedLogger = category.equals("#org.jetbrains.jps.incremental.java.JavaBuilder") ||
|
||||
category.equals("#org.jetbrains.jps.incremental.IncProjectBuilder");
|
||||
|
||||
return new Logger() {
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return affectedLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message, @Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message) {
|
||||
if (affectedLogger) {
|
||||
logger.info(stripper.strip(message));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message) {
|
||||
}
|
||||
@Override
|
||||
public void info(@NonNls String message, @Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable Throwable t) {
|
||||
}
|
||||
@Override
|
||||
public void warn(@NonNls String message, @Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message, @Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message) {
|
||||
if (affectedLogger) {
|
||||
logger.info(stripper.strip(message));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message, @Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(@NonNls String message, @Nullable Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(Level level) {
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void setLevel(Level level) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static RootStripper stripper = new RootStripper();
|
||||
@@ -142,9 +137,11 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
private final String groupName;
|
||||
private final String tempDir = FileUtil.toSystemDependentName(new File(System.getProperty("java.io.tmpdir")).getCanonicalPath());
|
||||
|
||||
private Logger.Factory oldFactory;
|
||||
private String baseDir;
|
||||
private String workDir;
|
||||
|
||||
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
|
||||
protected IncrementalTestCase(final String name) throws Exception {
|
||||
super(name);
|
||||
groupName = name;
|
||||
@@ -152,6 +149,9 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
oldFactory = Logger.ourFactory;
|
||||
Logger.setFactory(new MyFactory());
|
||||
|
||||
super.setUp();
|
||||
|
||||
baseDir = PathManagerEx.getTestDataPath() + File.separator + "compileServer" + File.separator + "incremental" + File.separator;
|
||||
@@ -175,8 +175,13 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
super.tearDown();
|
||||
}
|
||||
finally {
|
||||
closeAppender();
|
||||
delete(new File(workDir));
|
||||
try {
|
||||
closeAppender();
|
||||
delete(new File(workDir));
|
||||
}
|
||||
finally {
|
||||
Logger.setFactory(oldFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +347,5 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
finally {
|
||||
projectDescriptor.release();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,18 +237,12 @@ public class Mappings {
|
||||
this.myDelta = delta;
|
||||
}
|
||||
|
||||
void appendDependents(final Set<ClassRepr> classes, final Set<DependencyContext.S> result) {
|
||||
if (classes == null) {
|
||||
return;
|
||||
}
|
||||
void appendDependents(final ClassRepr c, final Set<DependencyContext.S> result) {
|
||||
final Collection<DependencyContext.S> depClasses = myDelta.myClassToClassDependency.get(c.name);
|
||||
|
||||
for (ClassRepr c : classes) {
|
||||
final Collection<DependencyContext.S> depClasses = myDelta.myClassToClassDependency.get(c.name);
|
||||
|
||||
if (depClasses != null) {
|
||||
for (DependencyContext.S className : depClasses) {
|
||||
result.add(className);
|
||||
}
|
||||
if (depClasses != null) {
|
||||
for (DependencyContext.S className : depClasses) {
|
||||
result.add(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -813,8 +807,6 @@ public class Mappings {
|
||||
final Set<ClassRepr> pastClasses = (Set<ClassRepr>)mySourceFileToClasses.get(fileName);
|
||||
final Set<DependencyContext.S> dependants = new HashSet<DependencyContext.S>();
|
||||
|
||||
self.appendDependents(pastClasses, dependants);
|
||||
|
||||
final Set<UsageRepr.Usage> affectedUsages = new HashSet<UsageRepr.Usage>();
|
||||
final Set<UsageRepr.AnnotationUsage> annotationQuery = new HashSet<UsageRepr.AnnotationUsage>();
|
||||
final Map<UsageRepr.Usage, Util.UsageConstraint> usageConstraints = new HashMap<UsageRepr.Usage, Util.UsageConstraint>();
|
||||
@@ -826,6 +818,8 @@ public class Mappings {
|
||||
final ClassRepr it = changed.first;
|
||||
final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;
|
||||
|
||||
self.appendDependents(it, dependants);
|
||||
|
||||
debug("Changed: ", it.name);
|
||||
|
||||
final int addedModifiers = diff.addedModifiers();
|
||||
@@ -1388,6 +1382,7 @@ public class Mappings {
|
||||
|
||||
debug("Processing removed classes:");
|
||||
for (ClassRepr c : classDiff.removed()) {
|
||||
self.appendDependents(c, dependants);
|
||||
debug("Adding usages of class ", c.name);
|
||||
affectedUsages.add(c.createUsage());
|
||||
}
|
||||
@@ -1412,71 +1407,69 @@ public class Mappings {
|
||||
debug("End of added classes processing.");
|
||||
|
||||
debug("Checking dependent files:");
|
||||
if (dependants != null) {
|
||||
final Set<DependencyContext.S> dependentFiles = new HashSet<DependencyContext.S>();
|
||||
final Set<DependencyContext.S> dependentFiles = new HashSet<DependencyContext.S>();
|
||||
|
||||
for (DependencyContext.S depClass : dependants) {
|
||||
final DependencyContext.S file = myClassToSourceFile.get(depClass);
|
||||
for (DependencyContext.S depClass : dependants) {
|
||||
final DependencyContext.S file = myClassToSourceFile.get(depClass);
|
||||
|
||||
if (file != null) {
|
||||
dependentFiles.add(file);
|
||||
}
|
||||
if (file != null) {
|
||||
dependentFiles.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
filewise:
|
||||
for (DependencyContext.S depFile : dependentFiles) {
|
||||
final File theFile = new File(myContext.getValue(depFile));
|
||||
|
||||
if (affectedFiles.contains(theFile) || compiledFiles.contains(theFile)) {
|
||||
continue filewise;
|
||||
}
|
||||
|
||||
filewise:
|
||||
for (DependencyContext.S depFile : dependentFiles) {
|
||||
final File theFile = new File(myContext.getValue(depFile));
|
||||
debug("Dependent file: ", depFile);
|
||||
final Collection<UsageRepr.Cluster> depClusters = mySourceFileToUsages.get(depFile);
|
||||
if (depClusters != null) {
|
||||
for (UsageRepr.Cluster depCluster : depClusters) {
|
||||
final Set<UsageRepr.Usage> depUsages = depCluster.getUsages();
|
||||
if (depUsages == null) {
|
||||
continue;
|
||||
}
|
||||
final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>(depUsages);
|
||||
|
||||
if (affectedFiles.contains(theFile) || compiledFiles.contains(theFile)) {
|
||||
continue filewise;
|
||||
}
|
||||
usages.retainAll(affectedUsages);
|
||||
|
||||
debug("Dependent file: ", depFile);
|
||||
final Collection<UsageRepr.Cluster> depClusters = mySourceFileToUsages.get(depFile);
|
||||
if (depClusters != null) {
|
||||
for (UsageRepr.Cluster depCluster : depClusters) {
|
||||
final Set<UsageRepr.Usage> depUsages = depCluster.getUsages();
|
||||
if (depUsages == null) {
|
||||
continue;
|
||||
}
|
||||
final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>(depUsages);
|
||||
if (!usages.isEmpty()) {
|
||||
for (UsageRepr.Usage usage : usages) {
|
||||
final Util.UsageConstraint constraint = usageConstraints.get(usage);
|
||||
|
||||
usages.retainAll(affectedUsages);
|
||||
|
||||
if (!usages.isEmpty()) {
|
||||
for (UsageRepr.Usage usage : usages) {
|
||||
final Util.UsageConstraint constraint = usageConstraints.get(usage);
|
||||
|
||||
if (constraint == null) {
|
||||
debug("Added file with no constraints");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
else {
|
||||
final Set<DependencyContext.S> residenceClasses = depCluster.getResidence(usage);
|
||||
for (DependencyContext.S residentName : residenceClasses) {
|
||||
if (constraint.checkResidence(residentName)) {
|
||||
debug("Added file with satisfied constraint");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (constraint == null) {
|
||||
debug("Added file with no constraints");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
}
|
||||
|
||||
if (annotationQuery.size() > 0) {
|
||||
final Collection<UsageRepr.Usage> annotationUsages = mySourceFileToAnnotationUsages.get(depFile);
|
||||
|
||||
for (UsageRepr.Usage usage : annotationUsages) {
|
||||
for (UsageRepr.AnnotationUsage query : annotationQuery) {
|
||||
if (query.satisfies(usage)) {
|
||||
debug("Added file due to annotation query");
|
||||
else {
|
||||
final Set<DependencyContext.S> residenceClasses = depCluster.getResidence(usage);
|
||||
for (DependencyContext.S residentName : residenceClasses) {
|
||||
if (constraint.checkResidence(residentName)) {
|
||||
debug("Added file with satisfied constraint");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (annotationQuery.size() > 0) {
|
||||
final Collection<UsageRepr.Usage> annotationUsages = mySourceFileToAnnotationUsages.get(depFile);
|
||||
|
||||
for (UsageRepr.Usage usage : annotationUsages) {
|
||||
for (UsageRepr.AnnotationUsage query : annotationQuery) {
|
||||
if (query.satisfies(usage)) {
|
||||
debug("Added file due to annotation query");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.ether.dependencyView;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import org.jetbrains.ether.RW;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -238,7 +239,7 @@ class TypeRepr {
|
||||
|
||||
switch (t.getSort()) {
|
||||
case Type.OBJECT:
|
||||
return context.getType(new ClassType(context.get(t.getClassName().replaceAll("\\.", "/"))));
|
||||
return context.getType(new ClassType(context.get(StringUtil.replaceChar(t.getClassName(), '.', '/'))));
|
||||
|
||||
case Type.ARRAY:
|
||||
return context.getType(new ArrayType(getType(context, t.getElementType())));
|
||||
|
||||
@@ -519,17 +519,18 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
|
||||
}
|
||||
roots[i++] = psi;
|
||||
}
|
||||
if (roots.length > 1) {
|
||||
Arrays.sort(roots, FILE_BY_LANGUAGE_ID);
|
||||
}
|
||||
// getPsiRoots() returns languages in the same order
|
||||
//if (roots.length > 1) {
|
||||
// Arrays.sort(roots, FILE_BY_LANGUAGE_ID);
|
||||
//}
|
||||
return roots;
|
||||
}
|
||||
private static final Comparator<PsiFile> FILE_BY_LANGUAGE_ID = new Comparator<PsiFile>() {
|
||||
@Override
|
||||
public int compare(PsiFile o1, PsiFile o2) {
|
||||
return o1.getLanguage().getID().compareTo(o2.getLanguage().getID());
|
||||
}
|
||||
};
|
||||
//private static final Comparator<PsiFile> FILE_BY_LANGUAGE_ID = new Comparator<PsiFile>() {
|
||||
// @Override
|
||||
// public int compare(PsiFile o1, PsiFile o2) {
|
||||
// return o1.getLanguage().getID().compareTo(o2.getLanguage().getID());
|
||||
// }
|
||||
//};
|
||||
|
||||
@Override
|
||||
public boolean isPhysical() {
|
||||
|
||||
@@ -55,7 +55,6 @@ import javax.swing.plaf.basic.BasicSliderUI;
|
||||
import java.awt.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -84,13 +83,15 @@ public class HectorComponent extends JPanel {
|
||||
final boolean notInLibrary =
|
||||
!fileIndex.isInLibrarySource(virtualFile) && !fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInContent(virtualFile);
|
||||
final FileViewProvider viewProvider = myFile.getViewProvider();
|
||||
List<Language> languages = new ArrayList<Language>(viewProvider.getLanguages());
|
||||
Collections.sort(languages, new Comparator<Language>() {
|
||||
@Override
|
||||
public int compare(Language o1, Language o2) {
|
||||
return o1.getID().compareTo(o2.getID());
|
||||
}
|
||||
});
|
||||
//List<Language> languages = new ArrayList<Language>(viewProvider.getLanguages());
|
||||
//Collections.sort(languages, new Comparator<Language>() {
|
||||
// @Override
|
||||
// public int compare(Language o1, Language o2) {
|
||||
// return o1.getID().compareTo(o2.getID());
|
||||
// }
|
||||
//});
|
||||
Collection<Language> languages = viewProvider.getLanguages();
|
||||
|
||||
for (Language language : languages) {
|
||||
@SuppressWarnings("UseOfObsoleteCollectionType")
|
||||
final Hashtable<Integer, JLabel> sliderLabels = new Hashtable<Integer, JLabel>();
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ProgramParametersUtil {
|
||||
Project project = configuration.getProject();
|
||||
Module module = getModule(configuration);
|
||||
|
||||
parameters.getProgramParametersList().addParametersString(configuration.getProgramParameters());
|
||||
parameters.getProgramParametersList().addParametersString(expandPath(configuration.getProgramParameters(), module, project));
|
||||
|
||||
parameters.setWorkingDirectory(getWorkingDir(configuration, project, module));
|
||||
|
||||
|
||||
@@ -296,15 +296,21 @@ public class FileStructurePopup implements Disposable {
|
||||
|
||||
if (!filter.equals(prefix)) {
|
||||
filter = prefix;
|
||||
myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myTree.repaint();
|
||||
//if (mySpeedSearch.isPopupActive()) {
|
||||
// mySpeedSearch.refreshSelection();
|
||||
//}
|
||||
}
|
||||
});
|
||||
final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock();
|
||||
try {
|
||||
myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myTree.repaint();
|
||||
//if (mySpeedSearch.isPopupActive()) {
|
||||
// mySpeedSearch.refreshSelection();
|
||||
//}
|
||||
}
|
||||
});
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
alarm.addRequest(this, 300);
|
||||
}
|
||||
@@ -575,14 +581,20 @@ public class FileStructurePopup implements Disposable {
|
||||
myFilteringStructure.rebuild();
|
||||
|
||||
final Object sel = selection;
|
||||
myAbstractTreeBuilder.refilter(sel, true, false).doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mySpeedSearch.isPopupActive()) {
|
||||
mySpeedSearch.refreshSelection();
|
||||
final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock();
|
||||
try {
|
||||
myAbstractTreeBuilder.refilter(sel, true, false).doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mySpeedSearch.isPopupActive()) {
|
||||
mySpeedSearch.refreshSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
chkFilter.setFocusable(false);
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -201,6 +202,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe
|
||||
container.forEach(new ValueContainer.ContainerAction<TIntArrayList>() {
|
||||
@Override
|
||||
public void perform(final int id, final TIntArrayList value) {
|
||||
ProgressManager.checkCanceled();
|
||||
final VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id);
|
||||
if (file == null || scope != null && !scope.contains(file)) {
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,21 +36,10 @@ public interface FileSystemTree extends Disposable {
|
||||
@Nullable
|
||||
VirtualFile getNewFileParent();
|
||||
|
||||
/**
|
||||
* @deprecated since tree updating is an asynchronous operation
|
||||
*/
|
||||
boolean select(VirtualFile file);
|
||||
|
||||
void select(VirtualFile file, @Nullable Runnable onDone);
|
||||
|
||||
void select(VirtualFile[] files, @Nullable Runnable onDone);
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated since tree updating is an asynchronous operation
|
||||
*/
|
||||
boolean expand(VirtualFile file);
|
||||
|
||||
void expand(VirtualFile file, @Nullable Runnable onDone);
|
||||
|
||||
void addListener(Listener listener, Disposable parent);
|
||||
@@ -63,7 +52,7 @@ public interface FileSystemTree extends Disposable {
|
||||
|
||||
boolean areHiddensShown();
|
||||
|
||||
void showHiddens(boolean showHiddens);
|
||||
void showHiddens(boolean showHidden);
|
||||
|
||||
interface Listener {
|
||||
void selectionChanged(List<VirtualFile> selection);
|
||||
|
||||
@@ -52,6 +52,7 @@ public class RareLogger extends Logger {
|
||||
if (fairSynch) {
|
||||
synchronized (lock) {
|
||||
super.put(key, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.put(key, value);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.notification;
|
||||
|
||||
import com.intellij.notification.impl.NotificationsConfigurationImpl;
|
||||
import com.intellij.notification.impl.NotificationsManagerImpl;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
@@ -105,7 +104,6 @@ public class LogModel implements Disposable {
|
||||
}
|
||||
|
||||
void removeNotification(Notification notification) {
|
||||
NotificationsManagerImpl.getNotificationsManagerImpl().remove(notification);
|
||||
synchronized (myNotifications) {
|
||||
myNotifications.remove(notification);
|
||||
}
|
||||
|
||||
+110
-37
@@ -16,46 +16,63 @@
|
||||
package com.intellij.notification.impl;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.notification.EventLog;
|
||||
import com.intellij.notification.LogModel;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.wm.CustomStatusBarWidget;
|
||||
import com.intellij.openapi.wm.IconLikeCustomStatusBarWidget;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.StatusBarWidget;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
*/
|
||||
public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.IconPresentation {
|
||||
public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget, IconLikeCustomStatusBarWidget {
|
||||
private static final Icon EMPTY_ICON = IconLoader.getIcon("/ide/notifications.png");
|
||||
private static final Icon ERROR_ICON = IconLoader.getIcon("/ide/error_notifications.png");
|
||||
private static final Icon WARNING_ICON = IconLoader.getIcon("/ide/warning_notifications.png");
|
||||
private static final Icon INFO_ICON = IconLoader.getIcon("/ide/info_notifications.png");
|
||||
public static final String WIDGET_ID = "Notifications";
|
||||
|
||||
private Icon myCurrentIcon = EMPTY_ICON;
|
||||
private StatusBar myStatusBar;
|
||||
private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
|
||||
|
||||
public IdeNotificationArea() {
|
||||
Disposer.register(this, myLogAlarm);
|
||||
|
||||
UISettings.getInstance().addUISettingsListener(new UISettingsListener() {
|
||||
@Override
|
||||
public void uiSettingsChanged(UISettings source) {
|
||||
updateStatus();
|
||||
}
|
||||
}, this);
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
EventLog.toggleLog(getProject());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
@@ -67,13 +84,7 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Project project = getProject();
|
||||
LogModel logModel = EventLog.getLogModel(project);
|
||||
ToolWindow eventLog = EventLog.getEventLog(project);
|
||||
if (eventLog != null && eventLog.isVisible()) {
|
||||
logModel.logShown();
|
||||
}
|
||||
updateStatus(logModel);
|
||||
updateStatus();
|
||||
myLogAlarm.addRequest(this, 100);
|
||||
}
|
||||
}.run();
|
||||
@@ -85,38 +96,42 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
|
||||
return PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext((Component) myStatusBar));
|
||||
}
|
||||
|
||||
public Consumer<MouseEvent> getClickConsumer() {
|
||||
return new Consumer<MouseEvent>() {
|
||||
public void consume(MouseEvent mouseEvent) {
|
||||
EventLog.toggleLog(getProject());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Icon getIcon() {
|
||||
return myCurrentIcon;
|
||||
}
|
||||
|
||||
public String getTooltipText() {
|
||||
int count = EventLog.getLogModel(getProject()).getNotifications().size();
|
||||
if (count > 0) {
|
||||
return String.format("%s notification%s pending", count, count == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
return "No new notifications";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String ID() {
|
||||
return WIDGET_ID;
|
||||
}
|
||||
|
||||
private void updateStatus(final LogModel model) {
|
||||
myCurrentIcon = getPendingNotificationsIcon(EMPTY_ICON, NotificationModel.getMaximumType(model.getNotifications()));
|
||||
private void updateStatus() {
|
||||
final Project project = getProject();
|
||||
LogModel logModel = EventLog.getLogModel(project);
|
||||
ToolWindow eventLog = EventLog.getEventLog(project);
|
||||
if (eventLog != null && eventLog.isVisible()) {
|
||||
logModel.logShown();
|
||||
}
|
||||
boolean stripesVisible = !UISettings.getInstance().HIDE_TOOL_STRIPES;
|
||||
ArrayList<Notification> notifications = logModel.getNotifications();
|
||||
RowIcon icon = new RowIcon(2);
|
||||
icon.setIcon(getPendingNotificationsIcon(EMPTY_ICON, getMaximumType(notifications)), 0);
|
||||
final int count = notifications.size();
|
||||
if (count > 0) {
|
||||
icon.setIcon(new TextIcon(this, String.valueOf(count)), 1);
|
||||
}
|
||||
if (stripesVisible && eventLog != null) {
|
||||
eventLog.setIcon(icon);
|
||||
setIcon(null);
|
||||
} else {
|
||||
setIcon(icon);
|
||||
}
|
||||
setToolTipText(count > 0 ? String.format("%s notification%s pending", count, count == 1 ? "" : "s") : "No new notifications");
|
||||
|
||||
myStatusBar.updateWidget(ID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private static Icon getPendingNotificationsIcon(Icon defIcon, final NotificationType maximumType) {
|
||||
if (maximumType != null) {
|
||||
switch (maximumType) {
|
||||
@@ -128,4 +143,62 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
|
||||
return defIcon;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static NotificationType getMaximumType(List<Notification> notifications) {
|
||||
NotificationType result = null;
|
||||
for (Notification notification : notifications) {
|
||||
if (NotificationType.ERROR == notification.getType()) {
|
||||
return NotificationType.ERROR;
|
||||
}
|
||||
|
||||
if (NotificationType.WARNING == notification.getType()) {
|
||||
result = NotificationType.WARNING;
|
||||
}
|
||||
else if (result == null && NotificationType.INFORMATION == notification.getType()) {
|
||||
result = NotificationType.INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class TextIcon implements Icon {
|
||||
private final String myStr;
|
||||
private final JComponent myComponent;
|
||||
private final int myWidth;
|
||||
|
||||
public TextIcon(IdeNotificationArea component, String str) {
|
||||
myStr = str;
|
||||
myComponent = component;
|
||||
myWidth = myComponent.getFontMetrics(calcFont()).stringWidth(myStr) + 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
Font originalFont = g.getFont();
|
||||
Color originalColor = g.getColor();
|
||||
g.setFont(calcFont());
|
||||
y += getIconHeight() - g.getFontMetrics().getDescent();
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
g.drawString(myStr, x + 1, y);
|
||||
|
||||
g.setFont(originalFont);
|
||||
g.setColor(originalColor);
|
||||
}
|
||||
|
||||
private Font calcFont() {
|
||||
return myComponent.getFont().deriveFont(Font.BOLD).deriveFont((float) getIconHeight() * 2 / 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return myWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return EMPTY_ICON.getIconHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.notification.impl;
|
||||
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.concurrency.ReentrantLock2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
*/
|
||||
public class NotificationModel {
|
||||
|
||||
private final Map<Notification, Pair<Project, Boolean>> myNotifications = new LinkedHashMap<Notification, Pair<Project, Boolean>>();
|
||||
|
||||
private final ReentrantLock2 myLock = new ReentrantLock2();
|
||||
|
||||
public void add(@NotNull final Notification notification, final @Nullable Project project) {
|
||||
try {
|
||||
myLock.acquire();
|
||||
myNotifications.put(notification, Pair.create(project, false));
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Notification remove(@NotNull final Notification notification) {
|
||||
try {
|
||||
myLock.acquire();
|
||||
myNotifications.remove(notification);
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
public void remove(@NotNull final Notification... notifications) {
|
||||
try {
|
||||
myLock.acquire();
|
||||
for (final Notification notification : notifications) {
|
||||
myNotifications.remove(notification);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private List<Notification> filterNotifications(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
LinkedList<Notification> result;
|
||||
if (myNotifications.isEmpty()) return Collections.emptyList();
|
||||
|
||||
result = new LinkedList<Notification>();
|
||||
for (final Map.Entry<Notification, Pair<Project, Boolean>> entry : myNotifications.entrySet()) {
|
||||
//noinspection ConstantConditions
|
||||
if (filter.fun(entry.getKey(), entry.getValue().first)) {
|
||||
result.addFirst(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void clear(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
List<Notification> result;
|
||||
try {
|
||||
myLock.acquire();
|
||||
result = filterNotifications(filter);
|
||||
myNotifications.keySet().removeAll(result);
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Notification> getFilteredNotifications(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
try {
|
||||
myLock.acquire();
|
||||
return Collections.unmodifiableList(filterNotifications(filter));
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static NotificationType getMaximumType(List<Notification> notifications) {
|
||||
NotificationType result = null;
|
||||
for (Notification notification : notifications) {
|
||||
if (NotificationType.ERROR == notification.getType()) {
|
||||
return NotificationType.ERROR;
|
||||
}
|
||||
|
||||
if (NotificationType.WARNING == notification.getType()) {
|
||||
result = NotificationType.WARNING;
|
||||
}
|
||||
else if (result == null && NotificationType.INFORMATION == notification.getType()) {
|
||||
result = NotificationType.INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+6
-63
@@ -34,7 +34,6 @@ import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
import com.intellij.ui.BalloonImpl;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -46,7 +45,6 @@ import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -54,8 +52,6 @@ import java.util.List;
|
||||
*/
|
||||
public class NotificationsManagerImpl extends NotificationsManager implements Notifications, ApplicationComponent {
|
||||
|
||||
private final NotificationModel myModel = new NotificationModel();
|
||||
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return "NotificationsManager";
|
||||
@@ -70,7 +66,7 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
|
||||
}
|
||||
|
||||
public void notify(@NotNull Notification notification) {
|
||||
doNotify(notification, NotificationDisplayType.BALLOON);
|
||||
doNotify(notification, NotificationDisplayType.BALLOON, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,50 +82,27 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
|
||||
@Override
|
||||
public void expire(@NotNull Notification notification) {
|
||||
EventLog.expire(notification);
|
||||
remove(notification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Notification> T[] getNotificationsOfType(Class<T> klass, @Nullable final Project project) {
|
||||
final List<Notification> notifications = myModel.getFilteredNotifications(createFilter(project, false));
|
||||
final List<T> result = new ArrayList<T>();
|
||||
for (final Notification notification : notifications) {
|
||||
for (Notification notification : EventLog.getLogModel(project).getNotifications()) {
|
||||
if (klass.isInstance(notification)) {
|
||||
//noinspection unchecked
|
||||
result.add((T) notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ArrayUtil.toObjectArray(result, klass);
|
||||
}
|
||||
|
||||
private static final PairFunction<Notification, Project, Boolean> ALL = new PairFunction<Notification, Project, Boolean>() {
|
||||
@NotNull
|
||||
public Boolean fun(final Notification notification, final Project project) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final PairFunction<Notification, Project, Boolean> APPLICATION = new PairFunction<Notification, Project, Boolean>() {
|
||||
@NotNull
|
||||
public Boolean fun(final Notification notification, final Project project) {
|
||||
return project == null;
|
||||
}
|
||||
};
|
||||
|
||||
public void clear(@Nullable Project project) {
|
||||
myModel.clear(createFilter(project, true));
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
myModel.clear(ALL);
|
||||
}
|
||||
|
||||
protected void doNotify(@NotNull Notification notification, @Nullable final NotificationDisplayType displayType) {
|
||||
doNotify(notification, displayType, null);
|
||||
}
|
||||
|
||||
public void doNotify(@NotNull final Notification notification, @Nullable NotificationDisplayType displayType, @Nullable final Project project) {
|
||||
public static void doNotify(@NotNull final Notification notification,
|
||||
@Nullable NotificationDisplayType displayType,
|
||||
@Nullable final Project project) {
|
||||
final NotificationsConfigurationImpl configuration = NotificationsConfigurationImpl.getNotificationsConfigurationImpl();
|
||||
if (!configuration.isRegistered(notification.getGroupId())) {
|
||||
configuration.register(notification.getGroupId(), displayType == null ? NotificationDisplayType.BALLOON : displayType);
|
||||
@@ -138,9 +111,6 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
|
||||
final NotificationSettings settings = NotificationsConfigurationImpl.getSettings(notification.getGroupId());
|
||||
boolean shouldLog = settings.isShouldLog();
|
||||
boolean displayable = settings.getDisplayType() != NotificationDisplayType.NONE;
|
||||
if (shouldLog && displayable) {
|
||||
myModel.add(notification, project);
|
||||
}
|
||||
|
||||
boolean willBeShown = displayable && NotificationsConfigurationImpl.getNotificationsConfigurationImpl().SHOW_BALLOONS;
|
||||
if (!shouldLog && !willBeShown) {
|
||||
@@ -318,31 +288,4 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
|
||||
return balloon;
|
||||
}
|
||||
|
||||
private static PairFunction<Notification, Project, Boolean> createFilter(@Nullable final Project project, final boolean strict) {
|
||||
return project == null ? APPLICATION : new ProjectFilter(project, strict);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Notification remove(Notification notification) {
|
||||
return myModel.remove(notification);
|
||||
}
|
||||
|
||||
public Collection<Notification> getAllNotifications(@Nullable final Project project) {
|
||||
return myModel.getFilteredNotifications(createFilter(project, false));
|
||||
}
|
||||
|
||||
private static class ProjectFilter implements PairFunction<Notification, Project, Boolean> {
|
||||
private final Project myProject;
|
||||
private final boolean myStrict;
|
||||
|
||||
private ProjectFilter(@NotNull final Project project, final boolean strict) {
|
||||
myProject = project;
|
||||
myStrict = strict;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Boolean fun(final Notification notification, final Project project) {
|
||||
return myStrict ? project == myProject : project == null || project == myProject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-15
@@ -18,12 +18,10 @@ package com.intellij.notification.impl;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationDisplayType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -40,18 +38,13 @@ public class ProjectNotificationsComponent implements Notifications, ProjectComp
|
||||
}
|
||||
|
||||
myProject.getMessageBus().connect().subscribe(TOPIC, this);
|
||||
Disposer.register(myProject, new Disposable() {
|
||||
public void dispose() {
|
||||
NotificationsManagerImpl.getNotificationsManagerImpl().clear(myProject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void projectOpened() {
|
||||
}
|
||||
|
||||
public void notify(@NotNull Notification notification) {
|
||||
NotificationsManagerImpl.getNotificationsManagerImpl().doNotify(notification, null, myProject);
|
||||
NotificationsManagerImpl.doNotify(notification, null, myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,14 +57,7 @@ public class ProjectNotificationsComponent implements Notifications, ProjectComp
|
||||
boolean shouldLog) {
|
||||
}
|
||||
|
||||
public void notify(@NotNull Notification notification, @NotNull NotificationDisplayType defaultDisplayType) {
|
||||
NotificationsManagerImpl.getNotificationsManagerImpl().doNotify(notification, defaultDisplayType, myProject);
|
||||
}
|
||||
|
||||
public void projectClosed() {
|
||||
for (final Notification notification : NotificationsManagerImpl.getNotificationsManagerImpl().getAllNotifications(myProject)) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDummyEnvironment() {
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -126,7 +126,9 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
|
||||
myFileSystemTree.select(parent, null);
|
||||
}
|
||||
}
|
||||
else if (file.isDirectory()) myFileSystemTree.expand(file);
|
||||
else if (file.isDirectory()) {
|
||||
myFileSystemTree.expand(file, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -336,7 +338,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
|
||||
}
|
||||
|
||||
protected VirtualFile[] getSelectedFiles() {
|
||||
return myFileSystemTree.getChoosenFiles();
|
||||
return myFileSystemTree.getChosenFiles();
|
||||
}
|
||||
|
||||
private final Map<String, LocalFileSystem.WatchRequest> myRequests = new HashMap<String, LocalFileSystem.WatchRequest>();
|
||||
|
||||
+23
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,13 +18,13 @@ package com.intellij.openapi.fileChooser.ex;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeStructure;
|
||||
import com.intellij.ide.util.treeView.NodeDescriptor;
|
||||
import com.intellij.ide.util.treeView.NodeRenderer;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileElement;
|
||||
import com.intellij.openapi.fileChooser.FileSystemTree;
|
||||
@@ -37,6 +37,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
|
||||
@@ -44,7 +45,6 @@ import com.intellij.ui.PopupHandler;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.treeStructure.SimpleNodeRenderer;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.containers.ConvertingIterator;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
@@ -62,8 +62,6 @@ import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class FileSystemTreeImpl implements FileSystemTree {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.chooser.FileSystemTreeImpl");
|
||||
|
||||
private final Tree myTree;
|
||||
private final FileTreeStructure myTreeStructure;
|
||||
private final AbstractTreeBuilder myTreeBuilder;
|
||||
@@ -76,15 +74,18 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
|
||||
private Map<VirtualFile, VirtualFile> myEverExpanded = new WeakHashMap<VirtualFile, VirtualFile>();
|
||||
|
||||
public FileSystemTreeImpl(@Nullable Project project, FileChooserDescriptor descriptor) {
|
||||
public FileSystemTreeImpl(@Nullable final Project project, final FileChooserDescriptor descriptor) {
|
||||
this(project, descriptor, new Tree(), null, null, null);
|
||||
myTree.setRootVisible(descriptor.isTreeRootVisible());
|
||||
myTree.setShowsRootHandles(true);
|
||||
}
|
||||
|
||||
public FileSystemTreeImpl(@Nullable Project project, FileChooserDescriptor descriptor, Tree tree, TreeCellRenderer renderer,
|
||||
final Runnable onInitialized,
|
||||
Convertor<TreePath, String> speedSearchConvertor) {
|
||||
public FileSystemTreeImpl(@Nullable final Project project,
|
||||
final FileChooserDescriptor descriptor,
|
||||
final Tree tree,
|
||||
@Nullable TreeCellRenderer renderer,
|
||||
@Nullable final Runnable onInitialized,
|
||||
@Nullable final Convertor<TreePath, String> speedSearchConverter) {
|
||||
myProject = project;
|
||||
myTreeStructure = new FileTreeStructure(project, descriptor);
|
||||
myDescriptor = descriptor;
|
||||
@@ -119,8 +120,8 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
}
|
||||
});
|
||||
|
||||
if (speedSearchConvertor != null) {
|
||||
new TreeSpeedSearch(myTree, speedSearchConvertor);
|
||||
if (speedSearchConverter != null) {
|
||||
new TreeSpeedSearch(myTree, speedSearchConverter);
|
||||
} else {
|
||||
new TreeSpeedSearch(myTree);
|
||||
}
|
||||
@@ -135,8 +136,7 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
registerTreeActions();
|
||||
|
||||
if (renderer == null) {
|
||||
renderer = new SimpleNodeRenderer() {
|
||||
|
||||
renderer = new NodeRenderer() {
|
||||
public void customizeCellRenderer(JTree tree,
|
||||
Object value,
|
||||
boolean selected,
|
||||
@@ -214,13 +214,13 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
return myTreeStructure.areHiddensShown();
|
||||
}
|
||||
|
||||
public void showHiddens(boolean showHiddens) {
|
||||
myTreeStructure.showHiddens(showHiddens);
|
||||
public void showHiddens(boolean showHidden) {
|
||||
myTreeStructure.showHiddens(showHidden);
|
||||
updateTree();
|
||||
}
|
||||
|
||||
public void updateTree() {
|
||||
myTreeBuilder.updateFromRoot();
|
||||
myTreeBuilder.queueUpdate();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
@@ -235,20 +235,8 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
return myTreeBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since tree updating is an asynchronous operation
|
||||
*/
|
||||
public boolean select(final VirtualFile file) {
|
||||
DefaultMutableTreeNode node = getNodeForFile(file);
|
||||
if (node == null) return false;
|
||||
else {
|
||||
TreeUtil.selectPath(myTree, new TreePath(node.getPath()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void select(VirtualFile file, @Nullable final Runnable onDone) {
|
||||
select(new VirtualFile[] {file}, onDone);
|
||||
select(new VirtualFile[]{file}, onDone);
|
||||
}
|
||||
|
||||
public void select(VirtualFile[] file, @Nullable final Runnable onDone) {
|
||||
@@ -282,23 +270,6 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
return new FileElement(selectFile, selectFile.getName());
|
||||
}
|
||||
|
||||
public boolean expand(VirtualFile directory) {
|
||||
if (!directory.isDirectory()) return false;
|
||||
DefaultMutableTreeNode node = getNodeForFile(directory);
|
||||
if (node == null) return false;
|
||||
myTree.expandPath(new TreePath(node.getPath()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DefaultMutableTreeNode getNodeForFile(VirtualFile file) {
|
||||
FileElement descriptor = getFileElementFor(file);
|
||||
if (descriptor == null) return null;
|
||||
|
||||
myTreeBuilder.buildNodeForElement(descriptor);
|
||||
return myTreeBuilder.getNodeForElement(descriptor);
|
||||
}
|
||||
|
||||
public Exception createNewFolder(final VirtualFile parentDirectory, final String newFolderName) {
|
||||
final Exception[] failReason = new Exception[] { null };
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
@@ -370,19 +341,15 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
public VirtualFile getNewFileParent() {
|
||||
if (getSelectedFile() != null) return getSelectedFile();
|
||||
|
||||
List<VirtualFile> roots = myDescriptor.getRoots();
|
||||
for (VirtualFile each : roots) {
|
||||
return each;
|
||||
}
|
||||
|
||||
return null;
|
||||
final List<VirtualFile> roots = myDescriptor.getRoots();
|
||||
return roots.size() > 0 ? roots.get(0) : null;
|
||||
}
|
||||
|
||||
public VirtualFile[] getSelectedFiles() {
|
||||
return collectSelectedFiles(new ConvertingIterator.IdConvertor<VirtualFile>());
|
||||
}
|
||||
|
||||
public VirtualFile[] getChoosenFiles() {
|
||||
public VirtualFile[] getChosenFiles() {
|
||||
return collectSelectedFiles(new Convertor<VirtualFile, VirtualFile>() {
|
||||
@Nullable
|
||||
public VirtualFile convert(VirtualFile file) {
|
||||
@@ -392,7 +359,7 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
});
|
||||
}
|
||||
|
||||
private VirtualFile[] collectSelectedFiles(Convertor<VirtualFile, VirtualFile> fileConvertor) {
|
||||
private VirtualFile[] collectSelectedFiles(Convertor<VirtualFile, VirtualFile> fileConverter) {
|
||||
TreePath[] paths = myTree.getSelectionPaths();
|
||||
if (paths == null) return VirtualFile.EMPTY_ARRAY;
|
||||
ArrayList<VirtualFile> files = new ArrayList<VirtualFile>(paths.length);
|
||||
@@ -401,7 +368,7 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
|
||||
if (!(node.getUserObject() instanceof FileNodeDescriptor)) return VirtualFile.EMPTY_ARRAY;
|
||||
FileNodeDescriptor descriptor = (FileNodeDescriptor)node.getUserObject();
|
||||
VirtualFile file = fileConvertor.convert(descriptor.getElement().getFile());
|
||||
VirtualFile file = fileConverter.convert(descriptor.getElement().getFile());
|
||||
if (file != null && file.isValid()) files.add(file);
|
||||
}
|
||||
return VfsUtil.toVirtualFileArray(files);
|
||||
@@ -419,7 +386,7 @@ public class FileSystemTreeImpl implements FileSystemTree {
|
||||
}
|
||||
for (VirtualFile root : roots) {
|
||||
if (root == null) continue;
|
||||
if (VfsUtil.isAncestor(root, file, false)) {
|
||||
if (VfsUtilCore.isAncestor(root, file, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,9 +125,11 @@ class StatusPanel extends JPanel {
|
||||
final Alarm alarm = getAlarm();
|
||||
myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && statusMessage != null && alarm != null;
|
||||
|
||||
if (myLogMode) {
|
||||
if (alarm != null) {
|
||||
alarm.cancelAllRequests();
|
||||
}
|
||||
|
||||
if (myLogMode) {
|
||||
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.speedSearch.SpeedSearch;
|
||||
import com.intellij.util.ImageLoader;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -1494,6 +1495,15 @@ public class AbstractPopup implements JBPopup {
|
||||
|
||||
if (doRevalidate) myContent.revalidate();
|
||||
}
|
||||
|
||||
public void setWarning(@NotNull String text) {
|
||||
JBLabel label = new JBLabel(text, UIUtil.getBalloonWarningIcon(), SwingConstants.CENTER);
|
||||
Color color = HintUtil.INFORMATION_COLOR;
|
||||
label.setOpaque(true);
|
||||
label.setBackground(color);
|
||||
label.setBorder(BorderFactory.createLineBorder(color, 3));
|
||||
myHeaderPanel.add(label, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
public void addListener(final JBPopupListener listener) {
|
||||
myListeners.add(listener);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,6 +27,7 @@ import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.psi.impl.source.tree.ASTStructure;
|
||||
import com.intellij.psi.tree.*;
|
||||
import com.intellij.testFramework.LightPlatformTestCase;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.diff.DiffTree;
|
||||
import com.intellij.util.diff.DiffTreeChangeBuilder;
|
||||
@@ -34,14 +35,12 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure;
|
||||
import com.intellij.util.diff.ShallowNodeComparator;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
private static final IFileElementType ROOT = new IFileElementType("ROOT", Language.ANY);
|
||||
|
||||
@@ -58,7 +57,11 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
private static final TokenSet WHITESPACE_SET = TokenSet.create(TokenType.WHITE_SPACE);
|
||||
private static final TokenSet COMMENT_SET = TokenSet.create(COMMENT);
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
|
||||
public PsiBuilderQuickTest() {
|
||||
PlatformTestCase.initPlatformLangPrefix();
|
||||
}
|
||||
|
||||
public void testPlain() {
|
||||
doTest("a<<b",
|
||||
new Parser() {
|
||||
@@ -77,7 +80,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComposites() {
|
||||
doTest("1(a(b)c)2(d)3",
|
||||
new Parser() {
|
||||
@@ -122,7 +124,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollapse() {
|
||||
doTest("a<<>>b",
|
||||
new Parser() {
|
||||
@@ -146,7 +147,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoneAndError() {
|
||||
doTest("a2b",
|
||||
new Parser() {
|
||||
@@ -169,7 +169,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiElement(LETTER)('b')\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrecedeAndDoneBefore() {
|
||||
doTest("ab",
|
||||
new Parser() {
|
||||
@@ -195,7 +194,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiElement(LETTER)('b')\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorBefore() {
|
||||
doTest("a1",
|
||||
new Parser() {
|
||||
@@ -219,7 +217,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiElement(DIGIT)('1')\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidityChecksOnDone() {
|
||||
doFailTest("a",
|
||||
new Parser() {
|
||||
@@ -234,7 +231,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
"Another not done marker added after this one. Must be done before this.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidityChecksOnDoneBefore1() {
|
||||
doFailTest("a",
|
||||
new Parser() {
|
||||
@@ -250,7 +246,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
"Another not done marker added after this one. Must be done before this.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidityChecksOnDoneBefore2() {
|
||||
doFailTest("a",
|
||||
new Parser() {
|
||||
@@ -265,7 +260,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
"'Before' marker precedes this one.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidityChecksOnTreeBuild1() {
|
||||
doFailTest("aa",
|
||||
new Parser() {
|
||||
@@ -277,7 +271,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
"Assertion failed: Parser produced no markers. Text:\naa");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidityChecksOnTreeBuild2() {
|
||||
doFailTest("aa",
|
||||
new Parser() {
|
||||
@@ -291,7 +284,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
"Tokens [LETTER] were not inserted into the tree. Text:\naa");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidityChecksOnTreeBuild3() {
|
||||
doFailTest("a ",
|
||||
new Parser() {
|
||||
@@ -306,7 +298,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
"Tokens [WHITE_SPACE] are outside of root element \"LETTER\". Text:\na ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitespaceTrimming() {
|
||||
doTest(" a b ",
|
||||
new Parser() {
|
||||
@@ -331,7 +322,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiWhiteSpace(' ')\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitespaceBalancingByErrors() {
|
||||
doTest("a b c",
|
||||
new Parser() {
|
||||
@@ -365,7 +355,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiElement(LETTER)('c')\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitespaceBalancingByEmptyComposites() {
|
||||
doTest("a b c",
|
||||
new Parser() {
|
||||
@@ -396,7 +385,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiElement(LETTER)('c')\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEdgeProcessors() {
|
||||
final WhitespacesAndCommentsBinder leftEdgeProcessor = new WhitespacesAndCommentsBinder() {
|
||||
@Override
|
||||
@@ -446,7 +434,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLightChameleon() {
|
||||
final IElementType CHAMELEON_2 = new MyLazyElementType("CHAMELEON_2") {
|
||||
@Override
|
||||
@@ -554,6 +541,7 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
|
||||
" PsiElement(OTHER)('}')\n");
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private static PsiBuilderImpl createBuilder(CharSequence text) {
|
||||
ParserDefinition parserDefinition = new ParserDefinition() {
|
||||
@NotNull
|
||||
|
||||
@@ -22,6 +22,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
|
||||
import static com.intellij.ui.GuiUtils.getTextWithoutMnemonicEscaping;
|
||||
|
||||
/**
|
||||
* Implement this interface and register it as extension to checkoutProvider extension point in order to provide checkout
|
||||
@@ -37,4 +40,10 @@ public interface CheckoutProvider {
|
||||
void directoryCheckedOut(File directory, VcsKey vcs);
|
||||
void checkoutCompleted();
|
||||
}
|
||||
|
||||
class CheckoutProviderComparator implements Comparator<CheckoutProvider> {
|
||||
public int compare(final CheckoutProvider o1, final CheckoutProvider o2) {
|
||||
return getTextWithoutMnemonicEscaping(o1.getVcsName()).compareTo(getTextWithoutMnemonicEscaping(o2.getVcsName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class CheckoutActionGroup extends ActionGroup implements DumbAware {
|
||||
|
||||
@@ -41,12 +40,7 @@ public class CheckoutActionGroup extends ActionGroup implements DumbAware {
|
||||
public AnAction[] getChildren(@Nullable AnActionEvent e) {
|
||||
if (myChildren == null) {
|
||||
final CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME);
|
||||
Arrays.sort(providers, new Comparator<CheckoutProvider>() {
|
||||
public int compare(final CheckoutProvider o1, final CheckoutProvider o2) {
|
||||
// not strict but will do
|
||||
return o1.getVcsName().compareTo(o2.getVcsName());
|
||||
}
|
||||
});
|
||||
Arrays.sort(providers, new CheckoutProvider.CheckoutProviderComparator());
|
||||
myChildren = new AnAction[providers.length];
|
||||
for (int i = 0; i < providers.length; i++) {
|
||||
CheckoutProvider provider = providers[i];
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.intellij.openapi.vcs.merge;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.impl.ProjectUtil;
|
||||
import com.intellij.ide.presentation.VirtualFilePresentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diff.ActionButtonPresentation;
|
||||
@@ -26,7 +25,6 @@ import com.intellij.openapi.diff.DiffRequestFactory;
|
||||
import com.intellij.openapi.diff.MergeRequest;
|
||||
import com.intellij.openapi.diff.impl.mergeTool.MergeVersion;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
@@ -37,10 +35,9 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.projectImport.ProjectOpenProcessor;
|
||||
import com.intellij.ui.ColoredTableCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
@@ -49,6 +46,7 @@ import com.intellij.util.ui.ColumnInfo;
|
||||
import com.intellij.util.ui.ListTableModel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -112,7 +110,8 @@ public class MultipleFileMergeDialog extends DialogWrapper {
|
||||
}
|
||||
};
|
||||
|
||||
public MultipleFileMergeDialog(Project project, final List<VirtualFile> files, final MergeProvider provider, MergeDialogCustomizer mergeDialogCustomizer) {
|
||||
public MultipleFileMergeDialog(@NotNull Project project, @NotNull final List<VirtualFile> files, @NotNull final MergeProvider provider,
|
||||
@NotNull MergeDialogCustomizer mergeDialogCustomizer) {
|
||||
super(project, false);
|
||||
myProject = project;
|
||||
myProjectManager = ProjectManagerEx.getInstanceEx();
|
||||
|
||||
+1
-7
@@ -22,18 +22,12 @@ import com.intellij.openapi.vcs.checkout.CheckoutAction;
|
||||
import com.intellij.ui.UIBundle;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class GetFromVcsAction extends WelcomePopupAction{
|
||||
|
||||
protected void fillActions(DefaultActionGroup group) {
|
||||
final CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME);
|
||||
Arrays.sort(providers, new Comparator<CheckoutProvider>() {
|
||||
public int compare(final CheckoutProvider o1, final CheckoutProvider o2) {
|
||||
// not strict but will do
|
||||
return o1.getVcsName().compareTo(o2.getVcsName());
|
||||
}
|
||||
});
|
||||
Arrays.sort(providers, new CheckoutProvider.CheckoutProviderComparator());
|
||||
for (CheckoutProvider provider : providers) {
|
||||
group.add(new CheckoutAction(provider));
|
||||
}
|
||||
|
||||
+1
@@ -95,6 +95,7 @@ public class AndroidRegenerateRJavaFileAction extends AnAction {
|
||||
CompilerManager.getInstance(project).executeTask(new CompileTask() {
|
||||
@Override
|
||||
public boolean execute(CompileContext context) {
|
||||
// todo: compatibility with background autogenerating
|
||||
AndroidCompileUtil.generate(new AndroidAptCompiler(), context);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -352,13 +352,21 @@ public class AndroidCompileUtil {
|
||||
}
|
||||
|
||||
public static void generate(final Module module, final GeneratingCompiler compiler) {
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(module);
|
||||
|
||||
if (facet != null) {
|
||||
facet.scheduleSourceRegenerating(compiler);
|
||||
}
|
||||
}
|
||||
|
||||
public static void doGenerate(final Module module, final GeneratingCompiler compiler) {
|
||||
final Project project = module.getProject();
|
||||
final AndroidProjectComponent component = ApplicationManager.getApplication().runReadAction(new Computable<AndroidProjectComponent>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public AndroidProjectComponent compute() {
|
||||
return !project.isDisposed() ? project.getComponent(AndroidProjectComponent.class) : null;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (component == null) {
|
||||
return;
|
||||
@@ -693,33 +701,33 @@ public class AndroidCompileUtil {
|
||||
}
|
||||
|
||||
for (final Resources resources : manager.getResourceElements()) {
|
||||
waitForSmartMode(project);
|
||||
waitForSmartMode(project);
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!resources.isValid() || facet.getModule().isDisposed() || project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!resources.isValid() || facet.getModule().isDisposed() || project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Attr attr : resources.getAttrs()) {
|
||||
final String name = attr.getName().getValue();
|
||||
for (final Attr attr : resources.getAttrs()) {
|
||||
final String name = attr.getName().getValue();
|
||||
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.ATTR.getName(), name));
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.ATTR.getName(), name));
|
||||
}
|
||||
}
|
||||
|
||||
for (final DeclareStyleable styleable : resources.getDeclareStyleables()) {
|
||||
final String name = styleable.getName().getValue();
|
||||
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.DECLARE_STYLEABLE.getName(), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final DeclareStyleable styleable : resources.getDeclareStyleables()) {
|
||||
final String name = styleable.getName().getValue();
|
||||
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.DECLARE_STYLEABLE.getName(), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
waitForSmartMode(project);
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.intellij.facet.FacetTypeRegistry;
|
||||
import com.intellij.lang.properties.IProperty;
|
||||
import com.intellij.lang.properties.psi.PropertiesFile;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.GeneratingCompiler;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
@@ -69,9 +70,14 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
import com.intellij.util.xml.ConvertContext;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import org.jetbrains.android.compiler.*;
|
||||
import org.jetbrains.android.compiler.AndroidAptCompiler;
|
||||
import org.jetbrains.android.compiler.AndroidCompileUtil;
|
||||
import org.jetbrains.android.compiler.AndroidIdlCompiler;
|
||||
import org.jetbrains.android.compiler.AndroidRenderscriptCompiler;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.importDependencies.ImportDependenciesUtil;
|
||||
import org.jetbrains.android.resourceManagers.LocalResourceManager;
|
||||
@@ -107,10 +113,27 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
private final Map<String, Map<String, PsiClass>> myClassMaps = new HashMap<String, Map<String, PsiClass>>();
|
||||
|
||||
private final Object myClassMapLock = new Object();
|
||||
|
||||
private final Map<Class<?>, MergingUpdateQueue> mySourcesAutogeneratingQueueMap = new HashMap<Class<?>, MergingUpdateQueue>();
|
||||
|
||||
public AndroidFacet(@NotNull Module module, String name, @NotNull AndroidFacetConfiguration configuration) {
|
||||
super(getFacetType(), module, name, configuration, null);
|
||||
configuration.setFacet(this);
|
||||
|
||||
mySourcesAutogeneratingQueueMap.put(AndroidAptCompiler.class, createSourceGeneratingQueue("AndroidAptAutogeneratingQueue"));
|
||||
mySourcesAutogeneratingQueueMap.put(AndroidIdlCompiler.class, createSourceGeneratingQueue("AndroidIdlAutogeneratingQueue"));
|
||||
mySourcesAutogeneratingQueueMap
|
||||
.put(AndroidRenderscriptCompiler.class, createSourceGeneratingQueue("AndroidRenderscriptAutogeneratingQueue"));
|
||||
}
|
||||
|
||||
private MergingUpdateQueue createSourceGeneratingQueue(@NotNull String name) {
|
||||
return new MergingUpdateQueue(name, 1000, false, null, this, null, false);
|
||||
}
|
||||
|
||||
private void activateSourceAutogenerating() {
|
||||
for (MergingUpdateQueue queue : mySourcesAutogeneratingQueueMap.values()) {
|
||||
queue.activate();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -366,6 +389,8 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project));
|
||||
}
|
||||
AndroidCompileUtil.generate(module, new AndroidRenderscriptCompiler());
|
||||
|
||||
activateSourceAutogenerating();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -710,4 +735,20 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
String moduleDirPath = getModuleDirPath();
|
||||
return moduleDirPath != null ? FileUtil.toSystemDependentName(moduleDirPath + path) : null;
|
||||
}
|
||||
|
||||
public void scheduleSourceRegenerating(@NotNull final GeneratingCompiler compiler) {
|
||||
final MergingUpdateQueue queue = mySourcesAutogeneratingQueueMap.get(compiler.getClass());
|
||||
|
||||
if (queue == null) {
|
||||
LOG.error("Autogenerating is not supported for compiler " + compiler.getClass().getCanonicalName());
|
||||
}
|
||||
else {
|
||||
queue.queue(new Update(this) {
|
||||
@Override
|
||||
public void run() {
|
||||
AndroidCompileUtil.doGenerate(getModule(), compiler);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.android.facet;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.intellij.facet.ui.FacetEditorContext;
|
||||
import com.intellij.facet.ui.FacetEditorTab;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
@@ -432,22 +431,17 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
|
||||
|
||||
runApt = runApt && myConfiguration.REGENERATE_R_JAVA && AndroidAptCompiler.isToCompileModule(myContext.getModule(), myConfiguration);
|
||||
runIdl = runIdl && myConfiguration.REGENERATE_JAVA_BY_AIDL;
|
||||
|
||||
if (runApt || runIdl) {
|
||||
final boolean finalRunApt = runApt;
|
||||
final boolean finalRunIdl = runIdl;
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Module module = myContext.getModule();
|
||||
Project project = module.getProject();
|
||||
if (finalRunApt) {
|
||||
AndroidCompileUtil.generate(module, new AndroidAptCompiler(), true);
|
||||
}
|
||||
if (finalRunIdl) {
|
||||
AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project));
|
||||
}
|
||||
}
|
||||
});
|
||||
final Module module = myContext.getModule();
|
||||
final Project project = module.getProject();
|
||||
|
||||
if (runApt) {
|
||||
AndroidCompileUtil.generate(module, new AndroidAptCompiler(), true);
|
||||
}
|
||||
if (runIdl) {
|
||||
AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+48
-6
@@ -39,8 +39,10 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
@@ -218,7 +220,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
|
||||
}
|
||||
|
||||
if (file instanceof PsiJavaFile) {
|
||||
createJavaResourceReference(project, editor, file, element, aPackage, resName, ResourceType.STRING.getName());
|
||||
createJavaResourceReference(facet.getModule(), editor, file, element, aPackage, resName, ResourceType.STRING.getName());
|
||||
}
|
||||
else {
|
||||
final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class);
|
||||
@@ -237,19 +239,28 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
|
||||
});
|
||||
}
|
||||
|
||||
private static void createJavaResourceReference(final Project project,
|
||||
private static void createJavaResourceReference(final Module module,
|
||||
final Editor editor,
|
||||
final PsiFile file,
|
||||
final PsiElement element,
|
||||
String aPackage,
|
||||
String resName,
|
||||
String resType) {
|
||||
final String aPackage,
|
||||
final String resName,
|
||||
final String resType) {
|
||||
final boolean extendsContext = getContainingInheritorOf(element, CONTEXT) != null;
|
||||
final String field = aPackage + ".R." + resType + '.' + AndroidResourceUtil.getRJavaFieldName(resName);
|
||||
final String rJavaFieldName = AndroidResourceUtil.getRJavaFieldName(resName);
|
||||
final String field = aPackage + ".R." + resType + '.' + rJavaFieldName;
|
||||
final String methodName = getGetterNameForResourceType(resType);
|
||||
assert methodName != null;
|
||||
final TemplateImpl template;
|
||||
final boolean inStaticContext = RefactoringUtil.isInStaticContext(element, null);
|
||||
final Project project = module.getProject();
|
||||
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
createStubResourceField(module, aPackage, resType, rJavaFieldName);
|
||||
}
|
||||
});
|
||||
|
||||
if (extendsContext && !inStaticContext) {
|
||||
if (ResourceType.STRING.getName().equals(resType)) {
|
||||
@@ -295,6 +306,37 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
|
||||
});
|
||||
}
|
||||
|
||||
private static void createStubResourceField(final Module module,
|
||||
final String aPackage,
|
||||
final String resType,
|
||||
final String fieldName) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Project project = module.getProject();
|
||||
final PsiClass[] classes =
|
||||
JavaPsiFacade.getInstance(project).findClasses(aPackage + ".R", GlobalSearchScope.moduleScope(module));
|
||||
if (classes.length == 1) {
|
||||
final PsiClass aClass = classes[0];
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
PsiClass resTypeClass = aClass.findInnerClassByName(resType, false);
|
||||
|
||||
if (resTypeClass == null) {
|
||||
resTypeClass = (PsiClass)aClass.add(factory.createClass(resType));
|
||||
}
|
||||
else if (resTypeClass.findFieldByName(fieldName, false) != null) {
|
||||
return;
|
||||
}
|
||||
final PsiField psiField = (PsiField)resTypeClass.add(factory.createField(fieldName, PsiType.INT));
|
||||
PsiUtil.setModifierProperty(psiField, PsiModifier.PUBLIC, true);
|
||||
PsiUtil.setModifierProperty(psiField, PsiModifier.STATIC, true);
|
||||
PsiUtil.setModifierProperty(psiField, PsiModifier.FINAL, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getPackage(@NotNull AndroidFacet facet) {
|
||||
Manifest manifest = facet.getManifest();
|
||||
|
||||
@@ -280,30 +280,10 @@ class GitPushResult {
|
||||
sb.append("<a href='UpdatedFiles'>View files updated during the push<a/>");
|
||||
}
|
||||
|
||||
NotificationListener viewUpdateFilesListener = new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
|
||||
if (event.getDescription().equals("UpdatedFiles")) {
|
||||
ProjectLevelVcsManagerEx vcsManager = ProjectLevelVcsManagerEx.getInstanceEx(myProject);
|
||||
UpdateInfoTree tree = vcsManager.showUpdateProjectInfo(updatedFiles, "Update", ActionInfo.UPDATE, false);
|
||||
tree.setBefore(myBeforeUpdateLabel);
|
||||
tree.setAfter(LocalHistory.getInstance().putSystemLabel(myProject, "After push"));
|
||||
}
|
||||
else {
|
||||
BrowserUtil.launchBrowser(event.getDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
NotificationListener viewUpdateFilesListener = new ViewUpdatedFilesNotificationListener(updatedFiles);
|
||||
|
||||
if (onlySuccess) {
|
||||
// display tool window balloon
|
||||
return new Notification(GitVcs.NOTIFICATION_GROUP_ID.getDisplayId(), title, sb.toString(), notificationType, viewUpdateFilesListener) {
|
||||
@Override public boolean isImportant() {
|
||||
return false; // don't highlight event log if push was totally successful
|
||||
}
|
||||
};
|
||||
return new MySuccessfulNotification(title, sb.toString(), notificationType, viewUpdateFilesListener);
|
||||
}
|
||||
|
||||
return new Notification(GitVcs.IMPORTANT_ERROR_NOTIFICATION.getDisplayId(), title, sb.toString(), notificationType, viewUpdateFilesListener);
|
||||
@@ -380,4 +360,37 @@ class GitPushResult {
|
||||
return commitNum + " " + StringUtil.pluralize("commit", commitNum);
|
||||
}
|
||||
|
||||
private static class MySuccessfulNotification extends Notification {
|
||||
public MySuccessfulNotification(@NotNull String title, @NotNull String message, @NotNull NotificationType notificationType,
|
||||
@NotNull NotificationListener listener) {
|
||||
super(GitVcs.NOTIFICATION_GROUP_ID.getDisplayId(), title, message, notificationType, listener);
|
||||
}
|
||||
|
||||
@Override public boolean isImportant() {
|
||||
return false; // don't highlight event log if push was totally successful
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewUpdatedFilesNotificationListener implements NotificationListener {
|
||||
private final UpdatedFiles myUpdatedFiles;
|
||||
|
||||
public ViewUpdatedFilesNotificationListener(UpdatedFiles updatedFiles) {
|
||||
myUpdatedFiles = updatedFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
|
||||
if (event.getDescription().equals("UpdatedFiles")) {
|
||||
ProjectLevelVcsManagerEx vcsManager = ProjectLevelVcsManagerEx.getInstanceEx(myProject);
|
||||
UpdateInfoTree tree = vcsManager.showUpdateProjectInfo(myUpdatedFiles, "Update", ActionInfo.UPDATE, false);
|
||||
tree.setBefore(myBeforeUpdateLabel);
|
||||
tree.setAfter(LocalHistory.getInstance().putSystemLabel(myProject, "After push"));
|
||||
}
|
||||
else {
|
||||
BrowserUtil.launchBrowser(event.getDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,12 @@ import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.repo.GitRepository;
|
||||
@@ -38,6 +37,7 @@ import git4idea.util.GitUIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.util.List;
|
||||
|
||||
@@ -53,12 +53,14 @@ import java.util.List;
|
||||
*/
|
||||
class GitBranchPopup {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GitBranchPopup.class);
|
||||
|
||||
private final Project myProject;
|
||||
private final GitRepositoryManager myRepositoryManager;
|
||||
private final GitVcsSettings myVcsSettings;
|
||||
private final GitVcs myVcs;
|
||||
private final GitMultiRootBranchConfig myMultiRootBranchConfig;
|
||||
|
||||
private final GitRepository myCurrentRepository;
|
||||
private final ListPopup myPopup;
|
||||
private GitMultiRootBranchConfig myMultiRootBranchConfig;
|
||||
private final ListPopupImpl myPopup;
|
||||
|
||||
ListPopup asListPopup() {
|
||||
return myPopup;
|
||||
@@ -76,31 +78,63 @@ class GitBranchPopup {
|
||||
private GitBranchPopup(@NotNull Project project, @NotNull GitRepository currentRepository) {
|
||||
myProject = project;
|
||||
myCurrentRepository = currentRepository;
|
||||
myRepositoryManager = GitRepositoryManager.getInstance(project);
|
||||
myVcs = GitVcs.getInstance(project);
|
||||
myVcsSettings = GitVcsSettings.getInstance(myProject);
|
||||
|
||||
GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(project);
|
||||
myMultiRootBranchConfig = new GitMultiRootBranchConfig(repositoryManager.getRepositories());
|
||||
|
||||
String title = "Git Branches";
|
||||
if (repositoryManager.moreThanOneRoot() && (myMultiRootBranchConfig.diverged() || getSyncSetting() == GitBranchSyncSetting.DONT)) {
|
||||
title += " on [" + GitUIUtil.getShortRepositoryName(currentRepository) + "]";
|
||||
}
|
||||
myMultiRootBranchConfig = new GitMultiRootBranchConfig(myRepositoryManager.getRepositories());
|
||||
|
||||
myPopup = JBPopupFactory.getInstance().createActionGroupPopup(
|
||||
String title = createPopupTitle(currentRepository);
|
||||
|
||||
myPopup = (ListPopupImpl) JBPopupFactory.getInstance().createActionGroupPopup(
|
||||
title, createActions(),
|
||||
SimpleDataContext.getProjectContext(project),
|
||||
JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true);
|
||||
|
||||
if (repositoryManager.moreThanOneRoot() && getSyncSetting() == GitBranchSyncSetting.NOT_DECIDED) {
|
||||
initBranchSyncPolicyIfNotInitialized();
|
||||
setCurrentBranchInfo();
|
||||
warnThatBranchesDivergedIfNeeded();
|
||||
}
|
||||
|
||||
private void initBranchSyncPolicyIfNotInitialized() {
|
||||
if (myRepositoryManager.moreThanOneRoot() && myVcsSettings.getSyncSetting() == GitBranchSyncSetting.NOT_DECIDED) {
|
||||
if (!myMultiRootBranchConfig.diverged()) {
|
||||
notifyAboutSyncedBranches();
|
||||
GitVcsSettings.getInstance(project).setSyncSetting(GitBranchSyncSetting.SYNC);
|
||||
myVcsSettings.setSyncSetting(GitBranchSyncSetting.SYNC);
|
||||
}
|
||||
else {
|
||||
GitVcsSettings.getInstance(project).setSyncSetting(GitBranchSyncSetting.DONT);
|
||||
myVcsSettings.setSyncSetting(GitBranchSyncSetting.DONT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String createPopupTitle(@NotNull GitRepository currentRepository) {
|
||||
String title = "Git Branches";
|
||||
if (myRepositoryManager.moreThanOneRoot() &&
|
||||
(myMultiRootBranchConfig.diverged() || myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT)) {
|
||||
title += " in " + GitUIUtil.getShortRepositoryName(currentRepository);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
private void setCurrentBranchInfo() {
|
||||
String currentBranchText = "Current branch";
|
||||
if (myRepositoryManager.moreThanOneRoot()) {
|
||||
if (myMultiRootBranchConfig.diverged()) {
|
||||
currentBranchText += " in " + GitUIUtil.getShortRepositoryName(myCurrentRepository) + ": " +
|
||||
GitBranchUiUtil.getDisplayableBranchText(myCurrentRepository);
|
||||
}
|
||||
else {
|
||||
currentBranchText += ": " + myMultiRootBranchConfig.getCurrentBranch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentBranchText += ": " + GitBranchUiUtil.getDisplayableBranchText(myCurrentRepository);
|
||||
}
|
||||
myPopup.setAdText(currentBranchText, SwingConstants.CENTER);
|
||||
}
|
||||
|
||||
private void notifyAboutSyncedBranches() {
|
||||
GitVcs.IMPORTANT_ERROR_NOTIFICATION.createNotification("Synchronous branch control enabled",
|
||||
"You have several Git roots in the project and they all are checked out at the same branch. " +
|
||||
@@ -109,8 +143,8 @@ class GitBranchPopup {
|
||||
NotificationType.INFORMATION, new NotificationListener() {
|
||||
@Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(myProject, GitVcs.getInstance(myProject).getConfigurable().getDisplayName());
|
||||
if (getSyncSetting() == GitBranchSyncSetting.DONT) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs.getConfigurable().getDisplayName());
|
||||
if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
@@ -118,11 +152,6 @@ class GitBranchPopup {
|
||||
}).notify(myProject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GitBranchSyncSetting getSyncSetting() {
|
||||
return GitVcsSettings.getInstance(myProject).getSyncSetting();
|
||||
}
|
||||
|
||||
private ActionGroup createActions() {
|
||||
DefaultActionGroup popupGroup = new DefaultActionGroup(null, false);
|
||||
|
||||
@@ -133,10 +162,6 @@ class GitBranchPopup {
|
||||
fillWithCommonRepositoryActions(popupGroup, repositoryManager);
|
||||
}
|
||||
else {
|
||||
if (myMultiRootBranchConfig.diverged() && userWantsSyncControl()) {
|
||||
warnThatBranchesDiverged(popupGroup);
|
||||
}
|
||||
|
||||
fillPopupWithCurrentRepositoryActions(popupGroup, createRepositoriesActions());
|
||||
}
|
||||
}
|
||||
@@ -145,19 +170,17 @@ class GitBranchPopup {
|
||||
}
|
||||
|
||||
popupGroup.addSeparator();
|
||||
//popupGroup.addAction(new ConfigureAction());
|
||||
return popupGroup;
|
||||
}
|
||||
|
||||
private boolean userWantsSyncControl() {
|
||||
return (getSyncSetting() != GitBranchSyncSetting.DONT);
|
||||
return (myVcsSettings.getSyncSetting() != GitBranchSyncSetting.DONT);
|
||||
}
|
||||
|
||||
private void fillWithCommonRepositoryActions(DefaultActionGroup popupGroup, GitRepositoryManager repositoryManager) {
|
||||
List<GitRepository> repositories = repositoryManager.getRepositories();
|
||||
String currentBranch = myMultiRootBranchConfig.getCurrentBranch();
|
||||
assert currentBranch != null : "Current branch can't be null if branches have not diverged";
|
||||
popupGroup.add(new GitBranchPopupActions.CurrentBranchAction(currentBranch, " in all roots"));
|
||||
popupGroup.add(new GitBranchPopupActions.NewBranchAction(myProject, repositories, myCurrentRepository));
|
||||
|
||||
popupGroup.addAll(createRepositoriesActions());
|
||||
@@ -175,9 +198,10 @@ class GitBranchPopup {
|
||||
}
|
||||
}
|
||||
|
||||
private void warnThatBranchesDiverged(@NotNull DefaultActionGroup popupGroup) {
|
||||
popupGroup.add(new BranchesHaveDivergedMessage(myCurrentRepository));
|
||||
popupGroup.addSeparator();
|
||||
private void warnThatBranchesDivergedIfNeeded() {
|
||||
if (myMultiRootBranchConfig.diverged() && userWantsSyncControl()) {
|
||||
myPopup.setWarning("Branches have diverged");
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultActionGroup createRepositoriesActions() {
|
||||
@@ -218,38 +242,7 @@ class GitBranchPopup {
|
||||
ActionGroup group = new GitBranchPopupActions(myRepository.getProject(), myRepository).createActions(null);
|
||||
return group.getChildren(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BranchesHaveDivergedMessage extends DumbAwareAction {
|
||||
|
||||
BranchesHaveDivergedMessage(GitRepository currentRepository) {
|
||||
super("Branches have diverged, showing current root " + GitUIUtil.getShortRepositoryName(currentRepository), "", IconLoader.getIcon("/general/ideFatalError.png"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
}
|
||||
|
||||
@Override public void update(AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(false); // this action works as a label
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Configure" opens a dialog to configure branches in the repository, i.e. set up tracked branches, fetch/push branches, etc.
|
||||
*/
|
||||
private static class ConfigureAction extends DumbAwareAction {
|
||||
public ConfigureAction() {
|
||||
super("Configure", null, IconLoader.getIcon("/general/ideOptions.png")); // TODO description
|
||||
}
|
||||
|
||||
@Override public void actionPerformed(AnActionEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
//e.getPresentation().setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.intellij.openapi.util.IconLoader;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.branch.GitBranchOperationsProcessor;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.util.GitUIUtil;
|
||||
import git4idea.validators.GitNewBranchNameValidator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -54,7 +53,7 @@ class GitBranchPopupActions {
|
||||
ActionGroup createActions(@Nullable DefaultActionGroup toInsert) {
|
||||
DefaultActionGroup popupGroup = new DefaultActionGroup(null, false);
|
||||
|
||||
popupGroup.addAction(new CurrentBranchAction(GitBranchUiUtil.getDisplayableBranchText(myRepository), "in root " + GitUIUtil.getShortRepositoryName(myRepository)));
|
||||
//popupGroup.addAction(new CurrentBranchAction(GitBranchUiUtil.getDisplayableBranchText(myRepository), "in root " + GitUIUtil.getShortRepositoryName(myRepository)));
|
||||
popupGroup.addAction(new NewBranchAction(myProject, Collections.singletonList(myRepository), myRepository));
|
||||
popupGroup.addAction(new CheckoutRevisionActions(myProject, myRepository));
|
||||
|
||||
@@ -81,22 +80,22 @@ class GitBranchPopupActions {
|
||||
return popupGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Current branch:" item which is disabled and is just a label to display the current branch.
|
||||
*/
|
||||
static class CurrentBranchAction extends DumbAwareAction {
|
||||
CurrentBranchAction(@NotNull String currentBranchName, @Nullable String rootName) {
|
||||
super("", String.format("Current branch is %s %s", currentBranchName, rootName), null);
|
||||
getTemplatePresentation().setText("Current Branch: " + currentBranchName, false); // no mnemonics
|
||||
}
|
||||
|
||||
@Override public void actionPerformed(AnActionEvent e) {
|
||||
}
|
||||
|
||||
@Override public void update(AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(false); // this action works as a label
|
||||
}
|
||||
}
|
||||
///**
|
||||
// * "Current branch:" item which is disabled and is just a label to display the current branch.
|
||||
// */
|
||||
//static class CurrentBranchAction extends DumbAwareAction {
|
||||
// CurrentBranchAction(@NotNull String currentBranchName, @Nullable String rootName) {
|
||||
// super("", String.format("Current branch is %s %s", currentBranchName, rootName), null);
|
||||
// getTemplatePresentation().setText("Current Branch: " + currentBranchName, false); // no mnemonics
|
||||
// }
|
||||
//
|
||||
// @Override public void actionPerformed(AnActionEvent e) {
|
||||
// }
|
||||
//
|
||||
// @Override public void update(AnActionEvent e) {
|
||||
// e.getPresentation().setEnabled(false); // this action works as a label
|
||||
// }
|
||||
//}
|
||||
|
||||
static class NewBranchAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
|
||||
@@ -132,7 +132,7 @@ public class GitFetcher {
|
||||
@NotNull GitFetchResult result,
|
||||
@Nullable String errorNotificationTitle, @NotNull Collection<? extends Exception> errors) {
|
||||
if (result.isSuccess()) {
|
||||
GitVcs.NOTIFICATION_GROUP_ID.createNotification("Fetched successfully", NotificationType.WARNING).notify(project);
|
||||
GitVcs.NOTIFICATION_GROUP_ID.createNotification("Fetched successfully", NotificationType.INFORMATION).notify(project);
|
||||
} else if (result.isCancelled()) {
|
||||
GitVcs.NOTIFICATION_GROUP_ID.createNotification("Fetch cancelled by user", NotificationType.WARNING).notify(project);
|
||||
} else if (result.isNotAuthorized()) {
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
// limitations under the License.
|
||||
package org.zmlx.hg4idea;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public enum HgFileStatusEnum {
|
||||
|
||||
ADDED('A'),
|
||||
@@ -29,7 +31,8 @@ public enum HgFileStatusEnum {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static HgFileStatusEnum valueOf(char c) {
|
||||
@Nullable
|
||||
public static HgFileStatusEnum parse(char c) {
|
||||
for (HgFileStatusEnum status : HgFileStatusEnum.values()) {
|
||||
if (status.id == c) {
|
||||
return status;
|
||||
|
||||
@@ -160,7 +160,12 @@ public class HgStatusCommand {
|
||||
LOG.warn("Unexpected line in status '" + line + '\'');
|
||||
continue;
|
||||
}
|
||||
HgFileStatusEnum status = HgFileStatusEnum.valueOf(line.charAt(STATUS_INDEX));
|
||||
char statusChar = line.charAt(STATUS_INDEX);
|
||||
HgFileStatusEnum status = HgFileStatusEnum.parse(statusChar);
|
||||
if (status == null) {
|
||||
LOG.error("Unknown status [" + statusChar + "] in line [" + line + "]");
|
||||
continue;
|
||||
}
|
||||
File ioFile = new File(repo.getPath(), line.substring(2));
|
||||
if (HgFileStatusEnum.COPY == status && previous != null
|
||||
&& previous.getStatus() == HgFileStatusEnum.ADDED) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.junit4;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.internal.AssumptionViolatedException;
|
||||
import org.junit.internal.builders.JUnit3Builder;
|
||||
import org.junit.internal.requests.ClassRequest;
|
||||
import org.junit.internal.runners.model.EachTestNotifier;
|
||||
import org.junit.runner.Description;
|
||||
@@ -148,6 +149,14 @@ public class JUnit4TestRunnerUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (clazz.getMethod("suite", new Class[0]) != null && !methodName.equals("suite")) {
|
||||
return Request.runner(new JUnit3Builder().runnerForClass(clazz)).filterWith(Description.createTestDescription(clazz, methodName));
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
//ignore
|
||||
}
|
||||
return Request.method(clazz, methodName);
|
||||
}
|
||||
appendTestClass(result, suiteClassName);
|
||||
|
||||
+11
-4
@@ -409,13 +409,20 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler {
|
||||
if (shouldFilter) {
|
||||
String charset = sourceVirtualFile.getCharset().name();
|
||||
String text = new String(FileUtil.loadFileBytes(sourceFile), charset);
|
||||
String escapedCharacters = "properties".equals(sourceVirtualFile.getExtension()) ? "\\" : null;
|
||||
text = MavenPropertyResolver.resolve(eachItem.getModule(),
|
||||
String escapedCharacters = sourceVirtualFile.getName().endsWith(".properties") ? "\\" : null;
|
||||
|
||||
PrintWriter printWriter = new PrintWriter(outputFile, charset);
|
||||
try {
|
||||
MavenPropertyResolver.doFilterText(eachItem.getModule(),
|
||||
text,
|
||||
eachItem.getProperties(),
|
||||
eachItem.getEscapeString(),
|
||||
escapedCharacters);
|
||||
FileUtil.writeToFile(outputFile, text.getBytes(charset));
|
||||
escapedCharacters,
|
||||
printWriter);
|
||||
}
|
||||
finally {
|
||||
printWriter.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
FileUtil.copy(sourceFile, outputFile);
|
||||
|
||||
+124
-79
@@ -16,39 +16,144 @@
|
||||
package org.jetbrains.idea.maven.dom;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.dom.model.MavenDomProfile;
|
||||
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
|
||||
import org.jetbrains.idea.maven.dom.model.MavenDomProperties;
|
||||
import org.jetbrains.idea.maven.dom.references.MavenFilteredPropertyPsiReferenceProvider;
|
||||
import org.jetbrains.idea.maven.project.MavenProject;
|
||||
import org.jetbrains.idea.maven.project.MavenProjectsManager;
|
||||
import org.jetbrains.idea.maven.server.MavenServerUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Properties;
|
||||
import java.util.Stack;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MavenPropertyResolver {
|
||||
public static final Pattern PATTERN = Pattern.compile("\\$\\{([^\\}]+?)\\}|@([^@]+?)@");
|
||||
public static final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}|@(.+?)@");
|
||||
|
||||
public static String resolve(Module module,
|
||||
String text,
|
||||
Properties additionalProperties,
|
||||
String propertyEscapeString,
|
||||
String escapedCharacters) {
|
||||
public static void doFilterText(Module module,
|
||||
String text,
|
||||
Properties additionalProperties,
|
||||
String propertyEscapeString,
|
||||
String escapedCharacters,
|
||||
Appendable out) throws IOException {
|
||||
MavenProjectsManager manager = MavenProjectsManager.getInstance(module.getProject());
|
||||
MavenProject mavenProject = manager.findProject(module);
|
||||
if (mavenProject == null) return text;
|
||||
return doResolve(text, mavenProject, additionalProperties, propertyEscapeString, escapedCharacters, new Stack<String>());
|
||||
if (mavenProject == null) {
|
||||
out.append(text);
|
||||
return;
|
||||
}
|
||||
|
||||
doFilterText(MavenFilteredPropertyPsiReferenceProvider.getDelimitersPattern(mavenProject),
|
||||
mavenProject,
|
||||
text,
|
||||
additionalProperties,
|
||||
propertyEscapeString,
|
||||
escapedCharacters,
|
||||
null,
|
||||
out);
|
||||
}
|
||||
|
||||
private static void doFilterText(Pattern pattern,
|
||||
MavenProject mavenProject,
|
||||
String text,
|
||||
Properties additionalProperties,
|
||||
@Nullable String escapeString,
|
||||
@Nullable String escapedCharacters,
|
||||
@Nullable Map<String, String> resolvedPropertiesParam,
|
||||
Appendable out) throws IOException {
|
||||
Map<String, String> resolvedProperties = resolvedPropertiesParam;
|
||||
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
int groupCount = matcher.groupCount();
|
||||
|
||||
int last = 0;
|
||||
while (matcher.find()) {
|
||||
if (escapeString != null) {
|
||||
int escapeStringStartIndex = matcher.start() - escapeString.length();
|
||||
if (escapeStringStartIndex >= last) {
|
||||
if (text.startsWith(escapeString, escapeStringStartIndex)) {
|
||||
out.append(text, last, escapeStringStartIndex);
|
||||
out.append(matcher.group());
|
||||
last = matcher.end();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.append(text, last, matcher.start());
|
||||
last = matcher.end();
|
||||
|
||||
String propertyName = null;
|
||||
|
||||
for (int i = 0; i < groupCount; i++) {
|
||||
propertyName = matcher.group(i + 1);
|
||||
if (propertyName != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert propertyName != null;
|
||||
|
||||
if (resolvedProperties == null) {
|
||||
resolvedProperties = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
String propertyValue = resolvedProperties.get(propertyName);
|
||||
if (propertyValue == null) {
|
||||
if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies
|
||||
out.append(matcher.group());
|
||||
continue;
|
||||
}
|
||||
|
||||
String resolved = doResolveProperty(propertyName, mavenProject, additionalProperties);
|
||||
if (resolved == null) {
|
||||
out.append(matcher.group());
|
||||
continue;
|
||||
}
|
||||
|
||||
resolvedProperties.put(propertyName, null);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
doFilterText(pattern, mavenProject, resolved, additionalProperties, null, null, resolvedProperties, sb);
|
||||
propertyValue = sb.toString();
|
||||
|
||||
resolvedProperties.put(propertyName, propertyValue);
|
||||
}
|
||||
|
||||
if (escapedCharacters == null) {
|
||||
out.append(propertyValue);
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < propertyValue.length(); i++) {
|
||||
char ch = propertyValue.charAt(i);
|
||||
if (escapedCharacters.indexOf(ch) != -1) {
|
||||
out.append('\\');
|
||||
}
|
||||
out.append(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.append(text, last, text.length());
|
||||
}
|
||||
|
||||
public static String resolve(String text, MavenDomProjectModel projectDom) {
|
||||
MavenProject mavenProject = MavenDomUtil.findProject(projectDom);
|
||||
if (mavenProject == null) return text;
|
||||
return doResolve(text, mavenProject, collectPropertiesFromDOM(mavenProject, projectDom), null, null, new Stack<String>());
|
||||
|
||||
StringBuilder res = new StringBuilder();
|
||||
try {
|
||||
doFilterText(PATTERN, mavenProject, text, collectPropertiesFromDOM(mavenProject, projectDom), null, null, null, res);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e); // never thrown
|
||||
}
|
||||
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
private static Properties collectPropertiesFromDOM(MavenProject project, MavenDomProjectModel projectDom) {
|
||||
@@ -75,78 +180,18 @@ public class MavenPropertyResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private static String doResolve(String text,
|
||||
MavenProject project,
|
||||
Properties additionalProperties,
|
||||
String escapeString,
|
||||
String escapedCharacters,
|
||||
Stack<String> resolutionStack) {
|
||||
Matcher matcher = PATTERN.matcher(text);
|
||||
|
||||
StringBuffer buff = new StringBuffer();
|
||||
StringBuffer dummy = new StringBuffer();
|
||||
int last = 0;
|
||||
while (matcher.find()) {
|
||||
String propText = matcher.group();
|
||||
String propName = matcher.group(1);
|
||||
if (propName == null) {
|
||||
propName = matcher.group(2);
|
||||
}
|
||||
|
||||
int tempLast = last;
|
||||
last = matcher.start() + propText.length();
|
||||
|
||||
if (escapeString != null) {
|
||||
int pos = matcher.start();
|
||||
if (pos > escapeString.length() && text.substring(pos - escapeString.length(), pos).equals(escapeString)) {
|
||||
buff.append(text.substring(tempLast, pos - escapeString.length()));
|
||||
buff.append(propText);
|
||||
matcher.appendReplacement(dummy, "");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String resolved = doResolveProperty(propName, project, additionalProperties);
|
||||
if (resolved == null) resolved = propText;
|
||||
if (!resolved.equals(propText) && !resolutionStack.contains(propName)) {
|
||||
resolutionStack.push(propName);
|
||||
resolved = doResolve(resolved, project, additionalProperties, escapeString, escapedCharacters, resolutionStack);
|
||||
resolutionStack.pop();
|
||||
}
|
||||
matcher.appendReplacement(buff, Matcher.quoteReplacement(escapeCharacters(resolved, escapedCharacters)));
|
||||
}
|
||||
matcher.appendTail(buff);
|
||||
|
||||
return buff.toString();
|
||||
}
|
||||
|
||||
private static String escapeCharacters(String text, String escapedCharacters) {
|
||||
if (StringUtil.isEmpty(escapedCharacters)) return text;
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char ch = text.charAt(i);
|
||||
if (escapedCharacters.indexOf(ch) != -1) {
|
||||
builder.append('\\');
|
||||
}
|
||||
builder.append(ch);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String doResolveProperty(String propName, MavenProject project, Properties additionalProperties) {
|
||||
String result;
|
||||
|
||||
result = MavenServerUtil.collectSystemProperties().getProperty(propName);
|
||||
if (result != null) return result;
|
||||
|
||||
if (propName.startsWith("project.") || propName.startsWith("pom.")) {
|
||||
if (propName.startsWith("pom.")) {
|
||||
propName = propName.substring("pom.".length());
|
||||
}
|
||||
else {
|
||||
propName = propName.substring("project.".length());
|
||||
}
|
||||
if (propName.startsWith("pom.")) {
|
||||
propName = propName.substring("pom.".length());
|
||||
}
|
||||
else if (propName.startsWith("project.")) {
|
||||
propName = propName.substring("project.".length());
|
||||
}
|
||||
|
||||
if (propName.equals("basedir")) return project.getDirectory();
|
||||
|
||||
+91
-11
@@ -15,23 +15,90 @@
|
||||
*/
|
||||
package org.jetbrains.idea.maven.dom.references;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceProvider;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.maven.dom.MavenDomUtil;
|
||||
import org.jetbrains.idea.maven.dom.MavenPropertyResolver;
|
||||
import org.jetbrains.idea.maven.project.MavenProject;
|
||||
import org.jetbrains.idea.maven.utils.MavenJDOMUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MavenFilteredPropertyPsiReferenceProvider extends PsiReferenceProvider {
|
||||
|
||||
private static final Key<Pattern> KEY = Key.create("MavenFilteredPropertyPsiReferenceProvider:delimitersKey");
|
||||
|
||||
public static final Pattern DEFAULT_DELIMITERS = MavenPropertyResolver.PATTERN;
|
||||
|
||||
@NotNull
|
||||
public static Pattern getDelimitersPattern(MavenProject mavenProject) {
|
||||
Pattern res = mavenProject.getCachedValue(KEY);
|
||||
if (res == null) {
|
||||
Element cfg = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-resources-plugin");
|
||||
if (cfg == null) {
|
||||
res = DEFAULT_DELIMITERS;
|
||||
}
|
||||
else {
|
||||
List<String> delimiters = MavenJDOMUtil.findChildrenValuesByPath(cfg, "delimiters", "delimiter");
|
||||
if (delimiters.isEmpty() || delimiters.size() > 10) {
|
||||
res = DEFAULT_DELIMITERS;
|
||||
}
|
||||
else {
|
||||
StringBuilder patternBuilder = new StringBuilder();
|
||||
|
||||
for (String delimiter : delimiters) {
|
||||
delimiter = delimiter.trim();
|
||||
if (delimiter.isEmpty()) continue;
|
||||
|
||||
int ind = delimiter.indexOf('*');
|
||||
if (ind >= 0) {
|
||||
appendDelimiter(patternBuilder, delimiter.substring(0, ind), delimiter.substring(ind + 1));
|
||||
}
|
||||
else {
|
||||
appendDelimiter(patternBuilder, delimiter, delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
// <useDefaultDelimiters> is not used if custom delimiters are not present.
|
||||
boolean useDefaultDelimiters = true;
|
||||
|
||||
String useDefaultDelimitersText = cfg.getChildText("useDefaultDelimiters");
|
||||
if (StringUtil.isNotEmpty(useDefaultDelimitersText)) {
|
||||
useDefaultDelimiters = Boolean.parseBoolean(useDefaultDelimitersText);
|
||||
}
|
||||
|
||||
if (useDefaultDelimiters) {
|
||||
appendDelimiter(patternBuilder, "${", "}");
|
||||
appendDelimiter(patternBuilder, "@", "@");
|
||||
}
|
||||
|
||||
res = Pattern.compile(patternBuilder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
res = mavenProject.putCachedValue(KEY, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void appendDelimiter(StringBuilder pattern, String prefix, String suffix) {
|
||||
if (pattern.length() > 0) {
|
||||
pattern.append('|');
|
||||
}
|
||||
pattern.append(Pattern.quote(prefix)).append("(.+?)").append(Pattern.quote(suffix));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
@@ -43,25 +110,38 @@ public class MavenFilteredPropertyPsiReferenceProvider extends PsiReferenceProvi
|
||||
MavenProject mavenProject = MavenDomUtil.findContainingProject(element);
|
||||
if (mavenProject == null) return PsiReference.EMPTY_ARRAY;
|
||||
|
||||
List<PsiReference> result = new ArrayList<PsiReference>();
|
||||
List<PsiReference> res = null;
|
||||
|
||||
Pattern pattern = getDelimitersPattern(mavenProject);
|
||||
|
||||
Matcher matcher = MavenPropertyResolver.PATTERN.matcher(text);
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
|
||||
int groupCount = matcher.groupCount();
|
||||
|
||||
while (matcher.find()) {
|
||||
String propertyName = matcher.group(1);
|
||||
int from;
|
||||
if (propertyName == null) {
|
||||
propertyName = matcher.group(2);
|
||||
from = matcher.start(2);
|
||||
String propertyName = null;
|
||||
int from = 0;
|
||||
|
||||
for (int i = 0; i < groupCount; i++) {
|
||||
propertyName = matcher.group(i + 1);
|
||||
if (propertyName != null) {
|
||||
from = matcher.start(i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
from = matcher.start(1);
|
||||
|
||||
assert propertyName != null;
|
||||
|
||||
if (res == null) {
|
||||
res = new ArrayList<PsiReference>();
|
||||
}
|
||||
|
||||
TextRange range = TextRange.from(from, propertyName.length());
|
||||
|
||||
result.add(new MavenFilteredPropertyPsiReference(mavenProject, element, propertyName, range, MavenPropertyPsiReferenceProvider.SOFT_DEFAULT));
|
||||
res.add(
|
||||
new MavenFilteredPropertyPsiReference(mavenProject, element, propertyName, range, MavenPropertyPsiReferenceProvider.SOFT_DEFAULT));
|
||||
}
|
||||
|
||||
return result.toArray(new PsiReference[result.size()]);
|
||||
return res == null ? PsiReference.EMPTY_ARRAY : res.toArray(new PsiReference[res.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -55,7 +55,7 @@ public class MavenExternalParameters {
|
||||
|
||||
params.setWorkingDirectory(parameters.getWorkingDirFile());
|
||||
|
||||
params.setJdk(getJdk(runnerSettings.getJreName()));
|
||||
params.setJdk(getJdk(runnerSettings, project != null && MavenRunner.getInstance(project).getState() == runnerSettings));
|
||||
|
||||
final String mavenHome = resolveMavenHome(coreSettings);
|
||||
|
||||
@@ -83,7 +83,8 @@ public class MavenExternalParameters {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Sdk getJdk(final String name) throws ExecutionException {
|
||||
private static Sdk getJdk(MavenRunnerSettings runnerSettings, boolean isGlobalRunnerSettings) throws ExecutionException {
|
||||
String name = runnerSettings.getJreName();
|
||||
if (name.equals(MavenRunnerSettings.USE_INTERNAL_JAVA)) {
|
||||
return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
|
||||
}
|
||||
@@ -106,7 +107,12 @@ public class MavenExternalParameters {
|
||||
}
|
||||
}
|
||||
|
||||
throw new ExecutionException(RunnerBundle.message("maven.java.not.found", name));
|
||||
if (isGlobalRunnerSettings) {
|
||||
throw new ExecutionException(RunnerBundle.message("maven.java.not.found.default.config", name));
|
||||
}
|
||||
else {
|
||||
throw new ExecutionException(RunnerBundle.message("maven.java.not.found", name));
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> createVMParameters(final List<String> list, final String mavenHome, final MavenRunnerSettings runnerSettings) {
|
||||
|
||||
+10
-9
@@ -187,20 +187,21 @@ public abstract class MavenRunnerConfigurable implements SearchableConfigurable,
|
||||
|
||||
}
|
||||
|
||||
private void fillComboboxJdk(MavenRunnerSettings data) {
|
||||
myJdkComboModel.removeAllElements();
|
||||
for (Pair<String, String> jdk : data.collectJdkNamesAndDescriptions()) {
|
||||
ComboBoxUtil.addToModel(myJdkComboModel, jdk.getFirst(), jdk.getSecond());
|
||||
}
|
||||
myJdkCombo.setModel(myJdkComboModel);
|
||||
}
|
||||
|
||||
void getData(MavenRunnerSettings data) {
|
||||
myRunInBackgroundCheckbox.setSelected(data.isRunMavenInBackground());
|
||||
myVMParametersEditor.setText(data.getVmOptions());
|
||||
mySkipTestsCheckBox.setSelected(data.isSkipTests());
|
||||
|
||||
fillComboboxJdk(data);
|
||||
Map<String, String> jdkMap = data.collectJdkNamesAndDescriptions();
|
||||
if (!jdkMap.containsKey(data.getJreName())) {
|
||||
jdkMap.put(data.getJreName(), data.getJreName());
|
||||
}
|
||||
|
||||
myJdkComboModel.removeAllElements();
|
||||
for (Map.Entry<String, String> entry : jdkMap.entrySet()) {
|
||||
ComboBoxUtil.addToModel(myJdkComboModel, entry.getKey(), entry.getValue());
|
||||
}
|
||||
myJdkCombo.setModel(myJdkComboModel);
|
||||
ComboBoxUtil.select(myJdkComboModel, data.getJreName());
|
||||
|
||||
myPropertiesPanel.setDataFromMap(data.getMavenProperties());
|
||||
|
||||
+5
-5
@@ -98,16 +98,16 @@ public class MavenRunnerSettings implements Cloneable {
|
||||
this.mavenProperties = mavenProperties;
|
||||
}
|
||||
|
||||
public List<Pair<String, String>> collectJdkNamesAndDescriptions() {
|
||||
List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
|
||||
public Map<String, String> collectJdkNamesAndDescriptions() {
|
||||
Map<String, String> result = new LinkedHashMap<String, String>();
|
||||
|
||||
for (Sdk projectJdk : ProjectJdkTable.getInstance().getSdksOfType(getSdkType())) {
|
||||
String name = projectJdk.getName();
|
||||
result.add(new Pair<String, String>(name, name));
|
||||
result.put(name, name);
|
||||
}
|
||||
|
||||
result.add(new Pair<String, String>(USE_INTERNAL_JAVA, RunnerBundle.message("maven.java.internal")));
|
||||
result.add(new Pair<String, String>(USE_JAVA_HOME, RunnerBundle.message("maven.java.home.env")));
|
||||
result.put(USE_INTERNAL_JAVA, RunnerBundle.message("maven.java.internal"));
|
||||
result.put(USE_JAVA_HOME, RunnerBundle.message("maven.java.home.env"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.module.StdModuleTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -42,6 +43,7 @@ import org.jetbrains.idea.maven.utils.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class MavenProject {
|
||||
@NotNull private final VirtualFile myFile;
|
||||
@@ -822,6 +824,23 @@ public class MavenProject {
|
||||
return Pair.create(type.getDefaultClassifier(), type.getDefaultExtension());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <V> V getCachedValue(Key<V> key) {
|
||||
//noinspection unchecked
|
||||
return (V)myState.myCache.get(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <V> V putCachedValue(Key<V> key, @NotNull V value) {
|
||||
ConcurrentHashMap<Key, Object> map = myState.myCache;
|
||||
Object oldValue = map.putIfAbsent(key, value);
|
||||
if (oldValue != null) {
|
||||
return (V)oldValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMavenId().toString();
|
||||
@@ -872,10 +891,13 @@ public class MavenProject {
|
||||
volatile List<MavenPlugin> myUnresolvedPluginsCache;
|
||||
volatile List<MavenArtifact> myUnresolvedExtensionsCache;
|
||||
|
||||
ConcurrentHashMap<Key, Object> myCache = new ConcurrentHashMap<Key, Object>();
|
||||
|
||||
@Override
|
||||
public State clone() {
|
||||
try {
|
||||
State result = (State)super.clone();
|
||||
myCache = new ConcurrentHashMap<Key, Object>();
|
||||
result.resetCache();
|
||||
return result;
|
||||
}
|
||||
@@ -889,6 +911,8 @@ public class MavenProject {
|
||||
myUnresolvedDependenciesCache = null;
|
||||
myUnresolvedPluginsCache = null;
|
||||
myUnresolvedExtensionsCache = null;
|
||||
|
||||
myCache.clear();
|
||||
}
|
||||
|
||||
public MavenProjectChanges getChanges(State other) {
|
||||
|
||||
@@ -28,6 +28,7 @@ maven.java.home.env=Use JAVA_HOME
|
||||
maven.java.home.undefined=JAVA_HOME environment variable not defined
|
||||
maven.java.home.invalid=JAVA_HOME environment vairable does not point to valid JRE ({0})
|
||||
maven.java.not.found=Cannot find JRE ''{0}''
|
||||
maven.java.not.found.default.config=Cannot find JRE ''{0}''. You can specify JRE to run maven goals in Settings -> Maver -> Runner
|
||||
|
||||
maven.run.configuration.name=Maven
|
||||
maven.run.configuration.description=Maven build
|
||||
|
||||
+41
@@ -63,6 +63,47 @@ public class ResourceFilteringTest extends MavenImportingTestCase {
|
||||
"value2=1");
|
||||
}
|
||||
|
||||
public void testCustomDelimiter() throws Exception {
|
||||
createProjectSubFile("resources/file.properties", "value1=${project.version}\n" +
|
||||
"value2=@project.version@\n" +
|
||||
"valueX=|\n" +
|
||||
"value3=|project.version|\n" +
|
||||
"value4=(project.version]");
|
||||
|
||||
importProject("<groupId>test</groupId>" +
|
||||
"<artifactId>project</artifactId>" +
|
||||
"<version>1</version>" +
|
||||
|
||||
"<build>" +
|
||||
" <resources>" +
|
||||
" <resource>" +
|
||||
" <directory>resources</directory>" +
|
||||
" <filtering>true</filtering>" +
|
||||
" </resource>" +
|
||||
" </resources>" +
|
||||
" <plugins>" +
|
||||
" <plugin>" +
|
||||
" <groupId>org.apache.maven.plugins</groupId>" +
|
||||
" <artifactId>maven-resources-plugin</artifactId>" +
|
||||
" <configuration>" +
|
||||
" <delimiters>" +
|
||||
" <delimiter>|</delimiter>" +
|
||||
" <delimiter>(*]</delimiter>" +
|
||||
" </delimiters>" +
|
||||
" </configuration>" +
|
||||
" </plugin>" +
|
||||
" </plugins>" +
|
||||
"</build>");
|
||||
|
||||
compileModules("project");
|
||||
|
||||
assertResult("target/classes/file.properties", "value1=1\n" +
|
||||
"value2=1\n" +
|
||||
"valueX=|\n" +
|
||||
"value3=1\n" +
|
||||
"value4=1");
|
||||
}
|
||||
|
||||
public void testPomArtifactId() throws Exception {
|
||||
createProjectSubFile("resources/file.properties", "value=${pom.artifactId}");
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -54,6 +55,8 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.MavenImportingTestCase;
|
||||
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
|
||||
import org.jetbrains.idea.maven.dom.references.MavenPsiElementWrapper;
|
||||
@@ -110,6 +113,11 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase {
|
||||
return findPsiFile(f).findReferenceAt(getEditorOffset(f));
|
||||
}
|
||||
|
||||
protected PsiReference getReferenceAt(VirtualFile f, int offset) throws IOException {
|
||||
configTest(f);
|
||||
return findPsiFile(f).findReferenceAt(offset);
|
||||
}
|
||||
|
||||
protected PsiElement getElementAtCaret(VirtualFile f) throws IOException {
|
||||
configTest(f);
|
||||
return findPsiFile(f).findElementAt(getEditorOffset(f));
|
||||
@@ -177,11 +185,35 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase {
|
||||
assertEquals(expectedText, ref.getCanonicalText());
|
||||
}
|
||||
|
||||
protected void assertResolved(VirtualFile file, PsiElement expected) throws IOException {
|
||||
protected void assertResolved(VirtualFile file, @NotNull PsiElement expected) throws IOException {
|
||||
doAssertResolved(file, expected);
|
||||
}
|
||||
|
||||
protected void assertResolved(VirtualFile file, PsiElement expected, String expectedText) throws IOException {
|
||||
@Nullable
|
||||
protected PsiReference getReference(VirtualFile file, @NotNull String referenceText) throws IOException {
|
||||
String text = VfsUtilCore.loadText(file);
|
||||
int index = text.indexOf(referenceText);
|
||||
assert index >= 0;
|
||||
|
||||
assert text.indexOf(referenceText, index + referenceText.length()) == -1 : "Reference text '" + referenceText + "' occurs more than one times";
|
||||
|
||||
return getReferenceAt(file, index);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiElement resolveReference(VirtualFile file, @NotNull String referenceText) throws IOException {
|
||||
PsiReference ref = getReference(file, referenceText);
|
||||
assertNotNull(ref);
|
||||
|
||||
PsiElement resolved = ref.resolve();
|
||||
if (resolved instanceof MavenPsiElementWrapper) {
|
||||
resolved = ((MavenPsiElementWrapper)resolved).getWrappee();
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
protected void assertResolved(VirtualFile file, @NotNull PsiElement expected, String expectedText) throws IOException {
|
||||
PsiReference ref = doAssertResolved(file, expected);
|
||||
assertEquals(expectedText, ref.getCanonicalText());
|
||||
}
|
||||
|
||||
+75
@@ -457,4 +457,79 @@ public class MavenFilteredPropertiesCompletionAndResolutionTest extends MavenDom
|
||||
assertEquals("foo=abc${bar}abc", findPsiFile(f).getText());
|
||||
assertEquals("bar=1", findPsiFile(filter).getText());
|
||||
}
|
||||
|
||||
public void testCustomDelimiters() throws Exception {
|
||||
createProjectSubDir("res");
|
||||
|
||||
importProject("<groupId>test</groupId>" +
|
||||
"<artifactId>project</artifactId>" +
|
||||
"<version>1</version>" +
|
||||
"<build>" +
|
||||
" <resources>" +
|
||||
" <resource>" +
|
||||
" <directory>res</directory>" +
|
||||
" <filtering>true</filtering>" +
|
||||
" </resource>" +
|
||||
" </resources>" +
|
||||
" <plugins>" +
|
||||
" <plugin>" +
|
||||
" <groupId>org.apache.maven.plugins</groupId>" +
|
||||
" <artifactId>maven-resources-plugin</artifactId>" +
|
||||
" <version>2.5</version>" +
|
||||
" <configuration>" +
|
||||
" <delimiters>" +
|
||||
" <delimiter>|</delimiter>" +
|
||||
" <delimiter>(*]</delimiter>" +
|
||||
" </delimiters>" +
|
||||
" </configuration>" +
|
||||
" </plugin>" +
|
||||
" </plugins>" +
|
||||
"</build>");
|
||||
|
||||
VirtualFile f = createProjectSubFile("res/foo1.properties",
|
||||
"foo1=${basedir}\n" +
|
||||
"foo2=|baseUri|\n" +
|
||||
"foo3=a(ve|rsion]");
|
||||
|
||||
assertNotNull(resolveReference(f, "basedir"));
|
||||
assertNotNull(resolveReference(f, "baseUri"));
|
||||
assertNotNull(getReference(f, "ve|rsion"));
|
||||
}
|
||||
|
||||
public void testDontUseDefaultDelimiter1() throws Exception {
|
||||
createProjectSubDir("res");
|
||||
|
||||
importProject("<groupId>test</groupId>" +
|
||||
"<artifactId>project</artifactId>" +
|
||||
"<version>1</version>" +
|
||||
"<build>" +
|
||||
" <resources>" +
|
||||
" <resource>" +
|
||||
" <directory>res</directory>" +
|
||||
" <filtering>true</filtering>" +
|
||||
" </resource>" +
|
||||
" </resources>" +
|
||||
" <plugins>" +
|
||||
" <plugin>" +
|
||||
" <groupId>org.apache.maven.plugins</groupId>" +
|
||||
" <artifactId>maven-resources-plugin</artifactId>" +
|
||||
" <version>2.5</version>" +
|
||||
" <configuration>" +
|
||||
" <delimiters>" +
|
||||
" <delimiter>|</delimiter>" +
|
||||
" </delimiters>" +
|
||||
" <useDefaultDelimiters>false</useDefaultDelimiters>" +
|
||||
" </configuration>" +
|
||||
" </plugin>" +
|
||||
" </plugins>" +
|
||||
"</build>");
|
||||
|
||||
VirtualFile f = createProjectSubFile("res/foo1.properties",
|
||||
"foo1=${basedir}\n" +
|
||||
"foo2=|baseUri|");
|
||||
|
||||
assert !(getReference(f, "basedir") instanceof MavenPropertyPsiReference);
|
||||
assertNotNull(resolveReference(f, "baseUri"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+29
-8
@@ -18,14 +18,35 @@ package org.jetbrains.idea.maven.dom;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import org.jetbrains.idea.maven.MavenImportingTestCase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenPropertyResolverTest extends MavenImportingTestCase {
|
||||
|
||||
private static String resolve(Module module,
|
||||
String text,
|
||||
Properties additionalProperties,
|
||||
String propertyEscapeString,
|
||||
String escapedCharacters) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try {
|
||||
MavenPropertyResolver.doFilterText(module, text, additionalProperties, propertyEscapeString, escapedCharacters, sb);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public void testResolvingProjectAttributes() throws Exception {
|
||||
importProject("<groupId>test</groupId>" +
|
||||
"<artifactId>project</artifactId>" +
|
||||
@@ -145,8 +166,8 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase {
|
||||
|
||||
importProject();
|
||||
assertEquals("${prop1}", resolve("${prop1}", myProjectPom));
|
||||
assertEquals("${prop3}", resolve("${prop2}", myProjectPom));
|
||||
assertEquals("${prop5}", resolve("${prop4}", myProjectPom));
|
||||
assertEquals("${prop3}", resolve("${prop3}", myProjectPom));
|
||||
assertEquals("${prop5}", resolve("${prop5}", myProjectPom));
|
||||
}
|
||||
|
||||
public void testSophisticatedPropertyNameDoesNotBreakResolver() throws Exception {
|
||||
@@ -262,13 +283,13 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase {
|
||||
"<version>1</version>");
|
||||
|
||||
assertEquals("foo ^project bar",
|
||||
MavenPropertyResolver.resolve(getModule("project"), "foo ^${project.artifactId} bar", new Properties(), "/", null));
|
||||
resolve(getModule("project"), "foo ^${project.artifactId} bar", new Properties(), "/", null));
|
||||
assertEquals("foo ${project.artifactId} bar",
|
||||
MavenPropertyResolver.resolve(getModule("project"), "foo ^^${project.artifactId} bar", new Properties(), "^^", null));
|
||||
resolve(getModule("project"), "foo ^^${project.artifactId} bar", new Properties(), "^^", null));
|
||||
assertEquals("project ${project.artifactId} project ${project.artifactId}",
|
||||
MavenPropertyResolver.resolve(getModule("project"),
|
||||
"${project.artifactId} ^${project.artifactId} ${project.artifactId} ^${project.artifactId}",
|
||||
new Properties(), "^", null));
|
||||
resolve(getModule("project"),
|
||||
"${project.artifactId} ^${project.artifactId} ${project.artifactId} ^${project.artifactId}",
|
||||
new Properties(), "^", null));
|
||||
}
|
||||
|
||||
public void testEscapingCharacters() throws Exception {
|
||||
@@ -280,7 +301,7 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase {
|
||||
" <foo>abc:def\\ghi</foo>" +
|
||||
"</properties>");
|
||||
|
||||
assertEquals("abc\\:def\\\\ghi", MavenPropertyResolver.resolve(getModule("project"), "${foo}", new Properties(), null, ":\\"));
|
||||
assertEquals("abc\\:def\\\\ghi", resolve(getModule("project"), "${foo}", new Properties(), null, ":\\"));
|
||||
}
|
||||
|
||||
private String resolve(String text, VirtualFile f) {
|
||||
|
||||
@@ -86,7 +86,7 @@ public class CreateFormAction extends AbstractCreateFormAction {
|
||||
final String packageName = aPackage.getQualifiedName();
|
||||
String fqClassName = null;
|
||||
if (myLastClassName != null) {
|
||||
fqClassName = packageName.length() == 0 ? newName : packageName + "." + myLastClassName;
|
||||
fqClassName = packageName.length() == 0 ? myLastClassName : packageName + "." + myLastClassName;
|
||||
}
|
||||
|
||||
final String formBody = createFormBody(fqClassName, "/com/intellij/uiDesigner/NewForm.xml",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.intellij.lang.xpath.xslt;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.XmlUnusedNamespaceInspection;
|
||||
import com.intellij.idea.Bombed;
|
||||
import com.intellij.javaee.ExternalResourceManagerEx;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -26,6 +27,8 @@ import com.intellij.util.ArrayUtil;
|
||||
import org.intellij.lang.xpath.TestBase;
|
||||
import org.intellij.lang.xpath.xslt.impl.XsltStuffProvider;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
@@ -127,6 +130,11 @@ public class XsltHighlightingTest extends TestBase {
|
||||
doXsltHighlighting();
|
||||
}
|
||||
|
||||
@Bombed(user = "Maxim.Mossienko", month = Calendar.FEBRUARY, day = 15)
|
||||
public void testXsltFreeze() throws Throwable {
|
||||
doXsltHighlighting();
|
||||
}
|
||||
|
||||
public void testTemplateWithPrefix() throws Throwable {
|
||||
myFixture.enableInspections(XmlUnusedNamespaceInspection.class);
|
||||
doXsltHighlighting();
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE xsl:stylesheet[
|
||||
<!ENTITY root "/doc">
|
||||
<!ENTITY elem "&root;/elem">
|
||||
]>
|
||||
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:variable name="sample" select="&elem;/elem2 | &elem;/elem3" />
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.htmlInspections;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.XmlErrorMessages;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
@@ -72,5 +73,6 @@ public class SwitchToHtml5Action implements LocalQuickFix, IntentionAction {
|
||||
|
||||
private static void applyFix(Project project) {
|
||||
ExternalResourceManagerEx.getInstanceEx().setDefaultHtmlDoctype(Html5SchemaProvider.HTML5_SCHEMA_LOCATION, project);
|
||||
DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -922,7 +922,12 @@ public class OldXmlParsing implements XmlElementType {
|
||||
|
||||
public void parseAttrValue(CompositeElement element, Lexer lexer) {
|
||||
while(lexer.getTokenType() != null) {
|
||||
addToken(element, lexer);
|
||||
if (lexer.getTokenType() == XML_ENTITY_REF_TOKEN) {
|
||||
final TreeElement children = parseEntityRef(lexer);
|
||||
element.rawAddChildren(children);
|
||||
} else {
|
||||
addToken(element, lexer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,5 +41,5 @@ public class XmlHighlighterColors {
|
||||
public static final TextAttributesKey HTML_ENTITY_REFERENCE = TextAttributesKey.createTextAttributesKey("HTML_ENTITY_REFERENCE");
|
||||
|
||||
public static final TextAttributesKey HTML_CODE =
|
||||
TextAttributesKey.createTextAttributesKey("HTML_CODE", HighlighterColors.TEXT.getDefaultAttributes().clone());
|
||||
TextAttributesKey.createTextAttributesKey("HTML_CODE", HighlighterColors.TEXT.getDefaultAttributes());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user