Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2012-02-03 19:38:48 +01:00
57 changed files with 1106 additions and 797 deletions
@@ -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);
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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() {
@@ -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>();
@@ -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();
@@ -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));
}
@@ -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));
}
}
}
@@ -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);
@@ -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);
@@ -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();
@@ -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()]);
}
}
@@ -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) {
@@ -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());
@@ -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
@@ -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());
}
@@ -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"));
}
}
@@ -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());
}