Merge remote branch 'origin/master'

This commit is contained in:
anna
2011-06-09 00:03:42 +04:00
40 changed files with 658 additions and 266 deletions
+8 -1
View File
@@ -238,7 +238,14 @@ public def layoutCommunityPlugins(String home) {
}
}
fileset(dir: "$home/plugins/xslt-debugger/rt/lib") {
includes: "**/*.jar, **/*.html"
include(name: "**/rmi-stubs.jar")
}
dir("rt") {
fileset(dir: "$home/plugins/xslt-debugger/rt/lib") {
include(name: "**/*.jar")
exclude(name: "**/rmi-stubs.jar")
include(name: "**/*.html")
}
}
}
@@ -46,6 +46,7 @@ public abstract class InspectionProfileEntry {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.InspectionProfileEntry");
private static final SkipDefaultValuesSerializationFilters DEFAULT_FILTER = new SkipDefaultValuesSerializationFilters();
private static Set<String> myBlackList = null;
private Boolean myUseNewSerializer = null;
@@ -189,7 +190,7 @@ public abstract class InspectionProfileEntry {
@SuppressWarnings("MethodMayBeStatic")
@Nullable
protected SerializationFilter getSerializationFilter() {
return new SkipDefaultValuesSerializationFilters();
return DEFAULT_FILTER;
}
/**
@@ -25,6 +25,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
@@ -57,7 +58,7 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable
return computeIconNow(element, request.getFlags());
}
};
private TIntObjectHashMap<Icon> myBaseIcon;
private static final Key<TIntObjectHashMap<Icon>> BASE_ICONS = Key.create("BASE_ICONS");
private static final Icon VISIBILITY_ICON_PLACEHOLDER = new EmptyIcon(Icons.PUBLIC_ICON);
public static final Icon ICON_PLACEHOLDER = IconLoader.getIcon("/nodes/nodePlaceholder.png");
@@ -86,28 +87,26 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable
@Nullable
private Icon computeIcon(final int flags) {
PsiElement psiElement = (PsiElement)this;
Icon baseIcon = LastComputedIcon.get(psiElement, flags);
if (baseIcon == null) {
if (myBaseIcon == null) {
myBaseIcon = new TIntObjectHashMap<Icon>(3);
}
if (!myBaseIcon.containsKey(flags)) {
myBaseIcon.put(flags, computeBaseIcon(flags));
}
baseIcon = myBaseIcon.get(flags);
}
if (!psiElement.isValid()) return null;
if (isToDeferIconLoading()) {
if (Registry.is("psi.deferIconLoading")) {
Icon baseIcon = LastComputedIcon.get(psiElement, flags);
if (baseIcon == null) {
TIntObjectHashMap<Icon> cache = getUserData(BASE_ICONS);
if (cache == null) {
cache = putUserDataIfAbsent(BASE_ICONS, new TIntObjectHashMap<Icon>());
}
synchronized (cache) {
if (!cache.containsKey(flags)) {
cache.put(flags, computeBaseIcon(flags));
}
baseIcon = cache.get(flags);
}
}
return IconDeferrer.getInstance().defer(baseIcon, new ElementIconRequest(psiElement, flags), ICON_COMPUTE);
}
else {
return computeIconNow(psiElement, flags);
}
}
protected boolean isToDeferIconLoading() {
return Registry.is("psi.deferIconLoading");
return computeIconNow(psiElement, flags);
}
@Nullable
@@ -534,8 +534,10 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
for (TextRange editable : editables) {
TextRange hostRange = ((DocumentWindow)documentRange).injectedToHost(editable);
HighlightInfo patched = HighlightInfo.createHighlightInfo(info.type, element, hostRange.getStartOffset(),
hostRange.getEndOffset(), info.description, info.toolTip);
if (patched != null) {
hostRange.getEndOffset(), info.description, info.toolTip);
if (patched != null &&
(patched.startOffset != patched.endOffset ||
info.startOffset == info.endOffset)) {
registerQuickFixes(tool, descriptor, patched, emptyActionRegistered);
outInfos.add(patched);
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
@@ -46,19 +47,18 @@ public abstract class BraceMatcherBasedSelectioner extends ExtendWordSelectionHa
final BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator);
final ArrayList<TextRange> result = new ArrayList<TextRange>();
final LinkedList<Pair<Integer, IElementType>> stack = new LinkedList<Pair<Integer, IElementType>>();
final LinkedList<Trinity<Integer, Integer, IElementType>> stack = new LinkedList<Trinity<Integer, Integer, IElementType>>();
while (!iterator.atEnd() && iterator.getStart() < totalRange.getEndOffset()) {
final Pair<Integer, IElementType> last;
final Trinity<Integer, Integer, IElementType> last;
if (braceMatcher.isLBraceToken(iterator, editorText, fileType)) {
stack.addLast(Pair.create(iterator.getStart(), iterator.getTokenType()));
stack.addLast(Trinity.create(iterator.getStart(), iterator.getEnd(), iterator.getTokenType()));
}
else if (braceMatcher.isRBraceToken(iterator, editorText, fileType)
&& !stack.isEmpty() && braceMatcher.isPairBraces((last = stack.getLast()).second, iterator.getTokenType())) {
&& !stack.isEmpty() && braceMatcher.isPairBraces((last = stack.getLast()).third, iterator.getTokenType())) {
stack.removeLast();
final int start = last.first;
result.addAll(expandToWholeLine(editorText, new TextRange(start, iterator.getEnd())));
int bodyStart = start + 1;
int bodyEnd = iterator.getEnd() - 1;
result.addAll(expandToWholeLine(editorText, new TextRange(last.first, iterator.getEnd())));
int bodyStart = last.second + 1;
int bodyEnd = iterator.getStart();
while (Character.isWhitespace(editorText.charAt(bodyStart))) bodyStart ++;
while (Character.isWhitespace(editorText.charAt(bodyEnd - 1))) bodyEnd --;
result.addAll(expandToWholeLine(editorText, new TextRange(bodyStart, bodyEnd)));
@@ -30,7 +30,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class PairedBraceMatcherAdapter implements NontrivialBraceMatcher {
public class PairedBraceMatcherAdapter implements NontrivialBraceMatcher {
private final PairedBraceMatcher myMatcher;
private final Language myLanguage;
@@ -47,22 +47,22 @@ class PairedBraceMatcherAdapter implements NontrivialBraceMatcher {
return -1;
}
public boolean isLBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
@Nullable
public BracePair findPair(boolean left, HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
final IElementType tokenType = iterator.getTokenType();
final BracePair[] pairs = myMatcher.getPairs();
for (BracePair pair : pairs) {
if (tokenType == pair.getLeftBraceType()) return true;
if (tokenType == (left? pair.getLeftBraceType() : pair.getRightBraceType())) return pair;
}
return false;
return null;
}
public boolean isLBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
return findPair(true, iterator, fileText, fileType) != null;
}
public boolean isRBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
final IElementType tokenType = iterator.getTokenType();
final BracePair[] pairs = myMatcher.getPairs();
for (BracePair pair : pairs) {
if (tokenType == pair.getRightBraceType()) return true;
}
return false;
return findPair(false, iterator, fileText, fileType) != null;
}
public IElementType getOppositeBraceTokenType(@NotNull final IElementType type) {
@@ -38,6 +38,7 @@ import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
@@ -134,6 +135,9 @@ public class FindUsagesManager implements JDOMExternalizable {
return true;
}
}
catch (IndexNotReadyException e) {
throw e;
}
catch (Exception e) {
LOG.error(e);
}
@@ -144,6 +148,9 @@ public class FindUsagesManager implements JDOMExternalizable {
return true;
}
}
catch (IndexNotReadyException e) {
throw e;
}
catch (Exception e) {
LOG.error(e);
}
@@ -20,23 +20,32 @@ import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.notification.impl.NotificationSettings;
import com.intellij.notification.impl.NotificationsConfigurable;
import com.intellij.notification.impl.NotificationsConfiguration;
import com.intellij.notification.impl.NotificationsManagerImpl;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.StatusBarEx;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -111,15 +120,20 @@ public class EventLog implements Notifications {
final NotificationType type = notification.getType();
view.print(mainText, type == NotificationType.ERROR
? ConsoleViewContentType.ERROR_OUTPUT
: type == NotificationType.INFORMATION
? ConsoleViewContentType.NORMAL_OUTPUT
: ConsoleViewContentType.WARNING_OUTPUT);
? ConsoleViewContentType.ERROR_OUTPUT
: type == NotificationType.INFORMATION
? ConsoleViewContentType.NORMAL_OUTPUT
: ConsoleViewContentType.WARNING_OUTPUT);
if (showLink) {
view.print(" ", ConsoleViewContentType.NORMAL_OUTPUT);
view.printHyperlink("more", new HyperlinkInfo() {
@Override
public void navigate(Project project) {
Balloon balloon = notification.getBalloon();
if (balloon != null) {
balloon.hide();
}
NotificationsManagerImpl.notifyByBalloon(notification, NotificationDisplayType.STICKY_BALLOON, project);
}
});
@@ -194,9 +208,25 @@ public class EventLog implements Notifications {
return project.getComponent(ProjectTracker.class);
}
public static class FactoryItself implements ToolWindowFactory, DumbAware {
public void createToolWindowContent(Project project, ToolWindow toolWindow) {
public void createToolWindowContent(final Project project, ToolWindow toolWindow) {
final ProjectTracker tracker = getProjectComponent(project);
final Content content = ContentFactory.SERVICE.getInstance().createContent(tracker.myConsoleView.getComponent(), "", false);
SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
panel.setContent(tracker.myConsoleView.getComponent());
DefaultActionGroup group = new DefaultActionGroup();
group.add(new DumbAwareAction("Settings", "Edit notification settings", IconLoader.getIcon("/general/secondaryGroup.png")) {
@Override
public void actionPerformed(AnActionEvent e) {
ShowSettingsUtil.getInstance().editConfigurable(project, new NotificationsConfigurable());
}
});
group.addAll(ContainerUtil.subList(Arrays.asList(tracker.myConsoleView.createConsoleActions()), 2)); // no next/prev
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, false);
toolbar.setTargetComponent(panel);
panel.setToolbar(toolbar.getComponent());
final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, "", false);
toolWindow.getContentManager().addContent(content);
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.FileAttribute;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,17 +56,10 @@ public class ForcedBuildFileAttribute {
if (is != null) {
try {
try {
/*
//todo[lene] IOUtil throws java.io.EOFException
at java.io.DataInputStream.readFully(DataInputStream.java:180)
at java.io.DataInputStream.readFully(DataInputStream.java:152)
at com.intellij.util.io.IOUtil.readString(IOUtil.java:40)
at com.intellij.buildfiles.ForcedBuildFileAttribute.getFrameworkIdOfBuildFile(ForcedBuildFileAttribute.java:59)
*/
if (is.available() == 0) {
return null;
}
return is.readUTF();
return IOUtil.readString(is);
}
finally {
is.close();
@@ -82,12 +76,12 @@ public class ForcedBuildFileAttribute {
public static void forceFileToFramework(VirtualFile file, String frameworkId, boolean value) {
if (value) {//belongs to other framework
String existingFrameworkId = getFrameworkIdOfBuildFile(file);
if (!StringUtil.isEmpty(existingFrameworkId) && !frameworkId.equals(existingFrameworkId)) {
return;
}
//belongs to other framework - do not override!
String existingFrameworkId = getFrameworkIdOfBuildFile(file);
if (!StringUtil.isEmpty(existingFrameworkId) && !frameworkId.equals(existingFrameworkId)) {
return;
}
if (value) {//write framework
forceBuildFile(file, frameworkId);
}
@@ -102,7 +96,7 @@ public class ForcedBuildFileAttribute {
final DataOutputStream os = FRAMEWORK_FILE_ATTRIBUTE.writeAttribute(file);
try {
try {
os.writeUTF(StringUtil.notNullize(value));
IOUtil.writeString(StringUtil.notNullize(value), os);
}
finally {
os.close();
@@ -20,17 +20,11 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: lene
@@ -72,68 +66,11 @@ public class ScriptRunnerUtil {
}
});
}
processHandler.startNotify();
//ProcessTerminatedListener.attach(processHandler, project);
return processHandler;
}
public static Pair<String, String[]> getExePathAndCommand(List<String> commandToExecute) {
@NonNls String exePath = "";
@NonNls List<String> parameters = new ArrayList<String>();
if (SystemInfo.isOS2) {
exePath = "cmd";
parameters.add("/c");
}
else if (SystemInfo.isWindows) {
if (!SystemInfo.isWindows9x) {
exePath = "cmd";
}
else {
exePath = "command.com";
}
parameters.add("/c");
/*if exe-path and at least one of parameters contain spaces the whole command must be quoted,
e.g. instead of
cmd /c "C:\Program Files\jdk1.5\bin\java" "-Dproperty=a b c" myclass
must be used
cmd /c ""C:\Program Files\jdk1.5\bin\java" "-Dproperty=a b c" myclass"
*/
boolean quoteWholeCommand = false;
for (int i = 1; i < commandToExecute.size(); i++) {
quoteWholeCommand |= commandToExecute.get(i).contains(" ");
}
quoteWholeCommand &= commandToExecute.size() > 0 && commandToExecute.get(0).contains(" ");
if (quoteWholeCommand) {
StringBuilder builder = new StringBuilder();
builder.append('"');
for (int i = 0; i < commandToExecute.size(); i++) {
if (i > 0) {
builder.append(' ');
}
builder.append(GeneralCommandLine.quote(commandToExecute.get(i)));
}
builder.append('"');
parameters.add(builder.toString());
return Pair.create(exePath, ArrayUtil.toStringArray(parameters));
}
}
int firstParamIdx = 0;
if (SystemInfo.isUnix) {
exePath = commandToExecute.get(0);
firstParamIdx = 1;
}
for (int i = firstParamIdx; i < commandToExecute.size(); i++) {
parameters.add(commandToExecute.get(i));
}
return Pair.create(exePath, ArrayUtil.toStringArray(parameters));
}
public static ScriptOutput executeScriptInConsoleWithFullOutput(String exePathString,
@Nullable VirtualFile scriptFile,
@Nullable String workingDirectory,
@@ -148,6 +85,7 @@ public class ScriptRunnerUtil {
final StringBuilder mergedOutput =
(scriptOutputType.readStandardOutput() && scriptOutputType.readErrorOutput()) ? new StringBuilder() : null;
addReadingProcessListener(scriptOutputType, processHandler, standardOutput, errorOutput, mergedOutput);
processHandler.startNotify();
if (!processHandler.waitFor(timeout)) {
LOG.warn("Process did not complete in " + timeout / 1000 + "s");
@@ -302,7 +302,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
if (!anchor.equals("__AUTODETECT__")) {
final List<String> parts = StringUtil.split(anchor, " ");
if (parts.size() < 2 || !myWidgetMap.keySet().contains(parts.get(1))) {
wid = "Notifications";
wid = "Memory";
before = true;
}
else {
@@ -122,6 +122,10 @@ public class ContainerUtil {
return result;
}
public static <T> List<T> subList(List<T> list, int from) {
return list.subList(from, list.size());
}
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Iterable<T> appendix) {
addAll(collection, appendix.iterator());
}
@@ -110,7 +110,6 @@ class BeanBinding implements Binding {
}
}
public void deserializeInto(final Object bean, final Element element) {
_deserializeInto(bean, element);
}
@@ -134,11 +133,11 @@ class BeanBinding implements Binding {
ArrayList<Binding> bindings = new ArrayList<Binding>(myPropertyBindings.keySet());
MultiMap<Binding, Object> data = new MultiMap<Binding, Object>();
final Object[] children = JDOMUtil.getChildNodesWithAttrs(e);
nextNode: for (Object child : children) {
nextNode:
for (Object child : children) {
if (XmlSerializerImpl.isIgnoredNode(child)) continue;
for (Binding binding : bindings) {
@@ -188,11 +187,9 @@ class BeanBinding implements Binding {
return Element.class;
}
private static String getTagName(Class<?> aClass) {
Tag tag = aClass.getAnnotation(Tag.class);
if (tag != null && tag.value().length() != 0) return tag.value();
return aClass.getSimpleName();
}
@@ -201,27 +198,26 @@ class BeanBinding implements Binding {
try {
List<Accessor> accessors = new ArrayList<Accessor>();
BeanInfo info = Introspector.getBeanInfo(aClass);
BeanInfo info = Introspector.getBeanInfo(aClass, Introspector.IGNORE_ALL_BEANINFO);
PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getName().equals(CLASS_PROPERTY)) continue;
final Method readMethod = propertyDescriptor.getReadMethod();
final Method writeMethod = propertyDescriptor.getWriteMethod();
if (readMethod == null) continue;
if (writeMethod == null) continue;
if (XmlSerializerImpl.findAnnotation(readMethod.getAnnotations(), Transient.class) != null ||
XmlSerializerImpl.findAnnotation(writeMethod.getAnnotations(), Transient.class) != null) continue;
accessors.add(new PropertyAccessor(propertyDescriptor));
if (readMethod != null && writeMethod != null &&
XmlSerializerImpl.findAnnotation(readMethod.getAnnotations(), Transient.class) == null &&
XmlSerializerImpl.findAnnotation(writeMethod.getAnnotations(), Transient.class) == null) {
accessors.add(new PropertyAccessor(propertyDescriptor));
}
}
Field[] fields = aClass.getFields();
for (Field field : fields) {
int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers) &&
final int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) &&
!Modifier.isFinal(modifiers) && !Modifier.isTransient(modifiers) &&
XmlSerializerImpl.findAnnotation(field.getAnnotations(), Transient.class) == null) {
accessors.add(new FieldAccessor(field));
}
@@ -260,7 +256,6 @@ class BeanBinding implements Binding {
return new AttributeBinding(accessor, attribute, xmlSerializer);
}
if (tag != null) {
if (tag.value().length() > 0) return new TagBinding(accessor, tag, xmlSerializer);
}
@@ -281,5 +276,4 @@ class BeanBinding implements Binding {
OptionTag optionTag = XmlSerializerImpl.findAnnotation(accessor.getAnnotations(), OptionTag.class);
return new OptionTagBinding(accessor, xmlSerializer, optionTag);
}
}
@@ -144,13 +144,17 @@ public class ChangesBrowserNode<T> extends DefaultMutableTreeNode {
}
public List<Change> getAllChangesUnder() {
List<Change> changes = new ArrayList<Change>();
return getAllObjectsUnder(Change.class);
}
public <T> List<T> getAllObjectsUnder(final Class<T> clazz) {
List<T> changes = new ArrayList<T>();
final Enumeration enumeration = depthFirstEnumeration();
while (enumeration.hasMoreElements()) {
ChangesBrowserNode child = (ChangesBrowserNode)enumeration.nextElement();
final Object value = child.getUserObject();
if (value instanceof Change) {
changes.add((Change)value);
if (clazz.isAssignableFrom(value.getClass())) {
changes.add((T) value);
}
}
return changes;
@@ -77,6 +77,7 @@ public class ChangesListView extends Tree implements TypeSafeDataProvider, Advan
@NonNls public static final String ourHelpId = "ideaInterface.changes";
@NonNls public static final DataKey<List<VirtualFile>> UNVERSIONED_FILES_DATA_KEY = DataKey.create("ChangeListView.UnversionedFiles");
@NonNls public static final DataKey<List<FilePath>> MISSING_FILES_DATA_KEY = DataKey.create("ChangeListView.MissingFiles");
@NonNls public static final DataKey<List<LocallyDeletedChange>> LOCALLY_DELETED_CHANGES = DataKey.create("ChangeListView.LocallyDeletedChanges");
@NonNls public static final DataKey<String> HELP_ID_DATA_KEY = DataKey.create(HELP_ID_KEY);
private ActionGroup myMenuGroup;
@@ -195,8 +196,9 @@ public class ChangesListView extends Tree implements TypeSafeDataProvider, Advan
}
else if (key == VcsDataKeys.MODIFIED_WITHOUT_EDITING_DATA_KEY) {
sink.put(VcsDataKeys.MODIFIED_WITHOUT_EDITING_DATA_KEY, getSelectedModifiedWithoutEditing());
}
else if (key == MISSING_FILES_DATA_KEY) {
} else if (key == LOCALLY_DELETED_CHANGES) {
sink.put(LOCALLY_DELETED_CHANGES, getSelectedLocallyDeletedChanges());
} else if (key == MISSING_FILES_DATA_KEY) {
sink.put(MISSING_FILES_DATA_KEY, getSelectedMissingFiles());
} else if (VcsDataKeys.HAVE_LOCALLY_DELETED == key) {
sink.put(VcsDataKeys.HAVE_LOCALLY_DELETED, haveLocallyDeleted());
@@ -265,6 +267,24 @@ public class ChangesListView extends Tree implements TypeSafeDataProvider, Advan
return new ArrayList<FilePath>(files);
}
private List<LocallyDeletedChange> getSelectedLocallyDeletedChanges() {
Set<LocallyDeletedChange> files = new HashSet<LocallyDeletedChange>();
final TreePath[] paths = getSelectionPaths();
if (paths != null) {
for (TreePath path : paths) {
if (path.getPathCount() > 1) {
ChangesBrowserNode firstNode = (ChangesBrowserNode)path.getPathComponent(1);
if (firstNode.getUserObject() == TreeModelBuilder.LOCALLY_DELETED_NODE) {
ChangesBrowserNode node = (ChangesBrowserNode)path.getLastPathComponent();
final List<LocallyDeletedChange> objectsUnder = node.getAllObjectsUnder(LocallyDeletedChange.class);
files.addAll(objectsUnder);
}
}
}
}
return new ArrayList<LocallyDeletedChange>(files);
}
private List<FilePath> getSelectedMissingFiles() {
return getSelectedFilePaths(TreeModelBuilder.LOCALLY_DELETED_NODE);
}
@@ -29,6 +29,7 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.actions.MoveChangesToAnotherListAction;
@@ -123,14 +124,16 @@ public class CommitHelper {
@Override
public NotificationInfo notifyFinished() {
final List<Change> changesFailedToCommit = processor.getChangesFailedToCommit();
String text = (myIncludedChanges.size() - changesFailedToCommit.size()) + " Change(s) Commited";
if (changesFailedToCommit.size() > 0) {
text += ", " + changesFailedToCommit.size() + " Change(s) Failed To Commit";
int failed = changesFailedToCommit.size();
int committed = myIncludedChanges.size() - failed;
String text = committed + " " + StringUtil.pluralize("change", committed) + " committed";
if (failed > 0) {
text += ", " + failed + " " + StringUtil.pluralize("change", failed) + " failed to commit";
}
final String title = "VCS Commit Finished";
AbstractCommonUpdateAction.NOTIFICATION_GROUP.createNotification(title + ", " + text, myCommitMessage, NotificationType.INFORMATION, null).notify( myProject);
return new NotificationInfo("VCS Commit", title, text, true);
AbstractCommonUpdateAction.NOTIFICATION_GROUP.createNotification(text, myCommitMessage, NotificationType.INFORMATION, null).notify( myProject);
return new NotificationInfo("VCS Commit", "VCS Commit Finished", text, true);
}
};
ProgressManager.getInstance().run(task);
@@ -19,6 +19,7 @@ import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -148,6 +149,14 @@ public class GithubOpenInBrowserAction extends DumbAwareAction {
if (branch.startsWith("origin/")){
branch = branch.substring(7);
}
BrowserUtil.launchBrowser("https://github.com/" + repoInfo + "/blob/" + branch + path.substring(rootPath.length()));
final StringBuilder builder = new StringBuilder();
builder.append("https://github.com/").append(repoInfo).append("/blob/").append(branch).append(path.substring(rootPath.length()));
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
if (editor != null){
final int line = editor.getCaretModel().getLogicalPosition().line;
builder.append("#L").append(line);
}
BrowserUtil.launchBrowser(builder.toString());
}
}
@@ -66,8 +66,13 @@ public class ConvertConcatenationToGstringIntention extends Intention {
else {
return;
}
String text = builder.toString();
if (builder.indexOf("\n") < 0 && builder.indexOf("\r") < 0) {
text = GrStringUtil.escapeSymbols(builder.toString(), "\"");
}
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(element.getProject());
final GrExpression newExpr = factory.createExpressionFromText(GrStringUtil.addQuotes(builder.toString(), true));
final GrExpression newExpr = factory.createExpressionFromText(GrStringUtil.addQuotes(text, true));
final GrExpression expression = ((GrExpression)element).replaceWithExpression(newExpr, true);
if (expression instanceof GrString) {
GrStringUtil.removeUnnecessaryBracesInGString((GrString)expression);
@@ -87,7 +92,6 @@ public class ConvertConcatenationToGstringIntention extends Intention {
}
else if (operand instanceof GrLiteral) {
String text = GrStringUtil.escapeSymbolsForGString(GrStringUtil.removeQuotes(operand.getText()), false);
if (text.contains("\n")) text = GrStringUtil.escapeSymbolsForGString(text, true);
builder.append(text);
}
else if (MyPredicate.satisfiedBy(operand, false)) {
@@ -152,8 +152,7 @@ public class ConvertGStringToStringIntention extends Intention {
}
if (text.length() == 0) return null;
String escaped = GrStringUtil.escapeSymbolsForString(text, false);
if (escaped.contains("\n")) escaped = GrStringUtil.escapeSymbolsForGString(escaped, true);
String escaped = GrStringUtil.escapeSymbolsForString(text, !text.contains("\n") && !text.contains("\r"));
return GrStringUtil.addQuotes(escaped, false);
}
}
@@ -50,10 +50,19 @@ public class PathExpression implements GroovyElementTypes {
*/
public static Result parsePathExprQualifierForExprStatement(PsiBuilder builder, GroovyParser parser) {
PsiBuilder.Marker marker = builder.mark();
final IElementType qualifierType = PrimaryExpression.parsePrimaryExpression(builder, parser);
final PsiBuilder.Marker marker1 = builder.mark();
IElementType qualifierType = PrimaryExpression.parsePrimaryExpression(builder, parser);
if (qualifierType != WRONGWAY) {
Result result;
if (isPathElementStart(builder)) {
if (builder.getTokenType() == mLPAREN && qualifierType == LITERAL) {
marker1.rollbackTo();
qualifierType = PrimaryExpression.parsePrimaryExpression(builder, parser, true);
assert qualifierType != WRONGWAY;
}
else {
marker1.drop();
}
PsiBuilder.Marker newMarker = marker.precede();
marker.drop();
if (checkForLCurly(builder)) {
@@ -67,12 +76,14 @@ public class PathExpression implements GroovyElementTypes {
}
}
else {
marker1.drop();
marker.drop();
result = INVOKED_EXPR;
}
return result;
}
else {
marker1.drop();
marker.drop();
return WRONG_WAY;
}
@@ -36,47 +36,56 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
*/
public class PrimaryExpression implements GroovyElementTypes {
public static IElementType parsePrimaryExpression(PsiBuilder builder, GroovyParser parser) {
if (TokenSets.BUILT_IN_TYPE.contains(builder.getTokenType())) {
public static IElementType parsePrimaryExpression(PsiBuilder builder, GroovyParser parser) {
return parsePrimaryExpression(builder, parser, false);
}
public static IElementType parsePrimaryExpression(PsiBuilder builder, GroovyParser parser, boolean literalsAsRefExprs) {
final IElementType tokenType = builder.getTokenType();
if (TokenSets.BUILT_IN_TYPE.contains(tokenType)) {
ParserUtils.eatElement(builder, BUILT_IN_TYPE_EXPRESSION);
return BUILT_IN_TYPE_EXPRESSION;
}
if (kTHIS == builder.getTokenType()) {
if (kTHIS == tokenType) {
ParserUtils.eatElement(builder, THIS_REFERENCE_EXPRESSION);
return THIS_REFERENCE_EXPRESSION;
}
if (kSUPER == builder.getTokenType()) {
if (kSUPER == tokenType) {
ParserUtils.eatElement(builder, SUPER_REFERENCE_EXPRESSION);
return SUPER_REFERENCE_EXPRESSION;
}
if (kNEW == builder.getTokenType()) {
if (kNEW == tokenType) {
return newExprParse(builder, parser);
}
if (mIDENT == builder.getTokenType()) {
if (mIDENT == tokenType) {
ParserUtils.eatElement(builder, REFERENCE_EXPRESSION);
return REFERENCE_EXPRESSION;
}
if (mGSTRING_BEGIN == builder.getTokenType()) {
if (mGSTRING_BEGIN == tokenType) {
return StringConstructorExpression.parse(builder, parser);
}
if (mREGEX_BEGIN == builder.getTokenType()) {
if (mREGEX_BEGIN == tokenType) {
return RegexConstructorExpression.parse(builder, parser);
}
if (mLBRACK == builder.getTokenType()) {
if (mLBRACK == tokenType) {
return ListOrMapConstructorExpression.parse(builder, parser);
}
if (mLPAREN == builder.getTokenType()) {
if (mLPAREN == tokenType) {
return parenthesizedExprParse(builder, parser);
}
if (mLCURLY == builder.getTokenType()) {
if (mLCURLY == tokenType) {
return OpenOrClosableBlock.parseClosableBlock(builder, parser);
}
if (TokenSets.CONSTANTS.contains(builder.getTokenType())) {
ParserUtils.eatElement(builder, LITERAL);
return LITERAL;
if (tokenType == mSTRING_LITERAL ||
tokenType == mGSTRING_LITERAL ||
tokenType == mREGEX_LITERAL) {
return ParserUtils.eatElement(builder, literalsAsRefExprs ? REFERENCE_EXPRESSION : LITERAL);
}
if (mWRONG_REGEX_LITERAL == builder.getTokenType()) {
if (TokenSets.CONSTANTS.contains(tokenType)) {
return ParserUtils.eatElement(builder, LITERAL);
}
if (mWRONG_REGEX_LITERAL == tokenType) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
builder.error(GroovyBundle.message("wrong.string"));
@@ -35,17 +35,6 @@ public class StringConstructorExpression implements GroovyElementTypes {
Marker sMarker = builder.mark();
if (ParserUtils.getToken(builder, mGSTRING_BEGIN)) {
ParserUtils.getToken(builder, mGSTRING_CONTENT);
if (mGSTRING_END.equals(builder.getTokenType())) {
sMarker.rollbackTo();
sMarker = builder.mark();
builder.advanceLexer();
builder.advanceLexer();
builder.advanceLexer();
sMarker.done(LITERAL);
return LITERAL;
}
while (ParserUtils.getToken(builder, mGSTRING_CONTENT) || mDOLLAR.equals(builder.getTokenType())) {
if (mDOLLAR.equals(builder.getTokenType())) {
stringConstructorValuePart(builder, parser);
@@ -155,9 +155,6 @@ public class GrArgumentLabelImpl extends GroovyPsiElementImpl implements GrArgum
if (value instanceof String) {
return (String)value;
}
if (value instanceof Number) {
return value.toString();
}
}
final IElementType elemType = element.getNode().getElementType();
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.PsiSubstitutorImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ComparatorUtil;
import com.intellij.util.containers.HashMap;
@@ -38,6 +39,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinary
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureImpl;
@@ -283,14 +285,11 @@ public class TypesUtil {
public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, PsiManager manager, GlobalSearchScope scope) {
if (lType == null || rType == null) return false;
if (rType instanceof GrTupleType) {
final GrTupleType tuple = (GrTupleType)rType;
if (tuple.getComponentTypes().length == 0) {
if (lType instanceof PsiArrayType ||
InheritanceUtil.isInheritor(lType, JAVA_UTIL_LIST) ||
InheritanceUtil.isInheritor(lType, JAVA_UTIL_SET)) {
return true;
}
if (rType instanceof GrTupleType && ((GrTupleType)rType).getComponentTypes().length == 0) {
if (lType instanceof PsiArrayType ||
InheritanceUtil.isInheritor(lType, JAVA_UTIL_LIST) ||
InheritanceUtil.isInheritor(lType, JAVA_UTIL_SET)) {
return true;
}
}
@@ -318,10 +317,54 @@ public class TypesUtil {
return true;
}
if (rType instanceof GrMapType || rType instanceof GrTupleType) {
Boolean result = isAssignableForNativeTypes(lType, (PsiClassType)rType, manager, scope);
if (result != null) return result.booleanValue();
}
return TypeConversionUtil.isAssignable(lType, rType);
}
@Nullable
private static Boolean isAssignableForNativeTypes(PsiType lType, PsiClassType rType, PsiManager manager, GlobalSearchScope scope) {
if (!(lType instanceof PsiClassType)) return null;
final PsiClassType.ClassResolveResult leftResult = ((PsiClassType)lType).resolveGenerics();
final PsiClassType.ClassResolveResult rightResult = rType.resolveGenerics();
final PsiClass leftClass = leftResult.getElement();
PsiClass rightClass = rightResult.getElement();
if (rightClass == null || leftClass == null) return null;
if (!InheritanceUtil.isInheritorOrSelf(rightClass, leftClass, true)) return Boolean.FALSE;
PsiSubstitutor rightSubstitutor = rightResult.getSubstitutor();
if (!leftClass.hasTypeParameters()) return Boolean.TRUE;
PsiSubstitutor leftSubstitutor = leftResult.getSubstitutor();
if (!leftClass.getManager().areElementsEquivalent(leftClass, rightClass)) {
rightSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(leftClass, rightClass, rightSubstitutor);
rightClass = leftClass;
}
else if (!rightClass.hasTypeParameters()) return Boolean.TRUE;
Iterator<PsiTypeParameter> li = PsiUtil.typeParametersIterator(leftClass);
Iterator<PsiTypeParameter> ri = PsiUtil.typeParametersIterator(rightClass);
while (li.hasNext()) {
if (!ri.hasNext()) return Boolean.FALSE;
PsiTypeParameter lp = li.next();
PsiTypeParameter rp = ri.next();
final PsiType typeLeft = leftSubstitutor.substitute(lp);
if (typeLeft == null) continue;
final PsiType typeRight = rightSubstitutor.substituteWithBoundsPromotion(rp);
if (typeRight == null) {
return Boolean.TRUE;
}
if (!isAssignableByMethodCallConversion(typeLeft, typeRight, manager, scope)) return Boolean.FALSE;
}
return Boolean.TRUE;
}
public static boolean isNumericType(PsiType type) {
if (type instanceof PsiClassType) {
return TYPE_TO_RANK.contains(type.getCanonicalText());
@@ -4,7 +4,9 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -27,76 +29,145 @@ public class GrStringUtil {
}
public static String escapeSymbolsForGString(String s, boolean escapeDoubleQuotes) {
return escapeSymbolsForGString(s, escapeDoubleQuotes, false);
}
public static String escapeSymbolsForGString(String s, boolean escapeDoubleQuotes, boolean forInjection) {
StringBuilder b = new StringBuilder();
final char[] chars = s.toCharArray();
final int len = chars.length - 1;
int i;
for (i = 0; i < len; i++) {
if (chars[i] == '\\') {
final char next = chars[i + 1];
if (next == '\'') {
b.append('\'');
i++;
}
else if (next == 'n') {
b.append('\n');
i++;
}
else if (escapeDoubleQuotes && next == '"') {
b.append('"');
i++;
}
else {
b.append(chars[i]);
i++;
b.append(chars[i]);
}
continue;
}
if (chars[i] == '"' || chars[i] == '$') b.append('\\');
b.append(chars[i]);
}
if (i == len) {
if (chars[i] == '"') b.append('\\');
b.append(chars[i]);
escapeStringCharacters(s.length(), s, escapeDoubleQuotes ? "$\"" : "$", false, forInjection, b);
if (!forInjection) {
unescapeCharacters(b, escapeDoubleQuotes ? "'" : "'\"", true);
}
return b.toString();
}
public static String escapeSymbolsForString(String s, boolean escapeQuotes) {
StringBuilder b = new StringBuilder();
final char[] chars = s.toCharArray();
final int len = chars.length - 1;
int i;
for (i = 0; i < len; i++) {
if (chars[i] == '\\') {
final char next = chars[i + 1];
if (next == '"' || next == '$') {
b.append(next);
return escapeSymbolsForString(s, escapeQuotes, false);
}
public static String escapeSymbolsForString(String s, boolean escapeQuotes, boolean forInjection) {
final StringBuilder builder = new StringBuilder();
escapeStringCharacters(s.length(), s, escapeQuotes ? "'" : "", false, forInjection, builder);
if (!forInjection) {
unescapeCharacters(builder, escapeQuotes ? "$\"" : "$'\"", true);
}
return builder.toString();
}
@NotNull
public static StringBuilder escapeStringCharacters(int length,
@NotNull String str,
@Nullable String additionalChars,
boolean escapeNR,
boolean escapeSlash,
@NotNull @NonNls StringBuilder buffer) {
for (int idx = 0; idx < length; idx++) {
char ch = str.charAt(idx);
switch (ch) {
case '\b':
buffer.append("\\b");
break;
case '\t':
buffer.append("\\t");
break;
case '\f':
buffer.append("\\f");
break;
case '\\':
if (escapeSlash) {
buffer.append("\\\\");
}
else {
buffer.append("\\");
}
break;
case '\n':
if (escapeNR) {
buffer.append("\\n");
}
else {
buffer.append('\n');
}
break;
case '\r':
if (escapeNR) {
buffer.append("\\r");
}
else {
buffer.append('\r');
}
break;
default:
if (additionalChars != null && additionalChars.indexOf(ch) > -1) {
buffer.append("\\").append(ch);
}
else if (Character.isISOControl(ch)) {
String hexCode = Integer.toHexString(ch).toUpperCase();
buffer.append("\\u");
int paddingCount = 4 - hexCode.length();
while (paddingCount-- > 0) {
buffer.append(0);
}
buffer.append(hexCode);
}
else {
buffer.append(ch);
}
}
}
return buffer;
}
public static void unescapeCharacters(StringBuilder builder, String toUnescape, boolean isMultiLine) {
for (int i = 0; i < builder.length(); i++) {
if (builder.charAt(i) != '\\') continue;
if (i + 1 == builder.length()) break;
char next = builder.charAt(i + 1);
if (next == 'n') {
if (isMultiLine) {
builder.replace(i, i + 2, "\n");
}
else if (next == 'n') {
b.append('\n');
}
else if (escapeQuotes && next == '\'') {
b.append(next);
}
else {
b.append('\\');
b.append(next);
}
else if (next == 'r') {
if (isMultiLine) {
builder.replace(i, i + 2, "\r");
}
}
else if (toUnescape.indexOf(next) != -1) {
builder.delete(i, i + 1);
}
else {
i++;
}
}
}
public static String escapeSymbols(String s, String toEscape) {
StringBuilder builder = new StringBuilder();
boolean escaped = false;
for (int i = 0; i < s.length(); i++) {
final char ch = s.charAt(i);
if (escaped) {
builder.append(ch);
escaped = false;
continue;
}
if (chars[i] == '\'') b.append('\\');
b.append(chars[i]);
}
if (ch == '\\') {
escaped = true;
}
if (toEscape.indexOf(ch) >= 0) {
builder.append('\\');
}
if (i == len) {
if (chars[i] == '\'') b.append('\\');
b.append(chars[i]);
builder.append(ch);
}
return b.toString();
return builder.toString();
}
public static String removeQuotes(@NotNull String s) {
@@ -121,7 +192,7 @@ public class GrStringUtil {
public static String addQuotes(String s, boolean forGString) {
if (forGString) {
if (s.contains("\n")) {
if (s.contains("\n") || s.contains("\r")) {
return TRIPLE_DOUBLE_QUOTES + s + TRIPLE_DOUBLE_QUOTES;
}
else {
@@ -129,7 +200,7 @@ public class GrStringUtil {
}
}
else {
if (s.contains("\n")) {
if (s.contains("\n") || s.contains("\r")) {
return TRIPLE_QUOTES + s + TRIPLE_QUOTES;
}
else {
@@ -16,20 +16,32 @@
package org.jetbrains.plugins.groovy.lang.resolve;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.AbstractElementManipulator;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
public class GroovyStringLiteralManipulator extends AbstractElementManipulator<GrLiteral> {
public GrLiteral handleContentChange(GrLiteral expr, TextRange range, String newContent) throws IncorrectOperationException {
if (!(expr.getValue() instanceof String)) throw new IncorrectOperationException("cannot handle content change");
String oldText = expr.getText();
newContent = StringUtil.escapeStringCharacters(newContent);
String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset());
if (oldText.startsWith("'")) {
newContent = GrStringUtil.escapeSymbolsForString(newContent, !oldText.startsWith("'''"), true);
}
else {
newContent = GrStringUtil.escapeSymbolsForGString(newContent, !oldText.startsWith("\"\"\""), true);
}
String newText;
if (range.getStartOffset() == 1 && (newContent.indexOf('\n') >= 0 || newContent.indexOf('\r') >= 0)) {
String corner = oldText.substring(0, 1) + oldText.substring(0, 1) + oldText.substring(0, 1);
newText = corner + newContent + corner;
}
else {
newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset());
}
final GrExpression newExpr = GroovyPsiElementFactory.getInstance(expr.getProject()).createExpressionFromText(newText);
PsiElement firstChild = expr.getFirstChild();
@@ -48,9 +60,18 @@ public class GroovyStringLiteralManipulator extends AbstractElementManipulator<G
}
public static TextRange getLiteralRange(String text) {
if (text.length() > 6 && text.startsWith("\"\"\"") && text.endsWith("\"\"\"")) {
return new TextRange(3, text.length() - 3);
int start = 1;
int fin = text.length();
String begin = text.substring(0, 1);
if (text.startsWith("\"\"\"") || text.startsWith("'''")) {
start += 2;
begin = text.substring(0, 3);
}
return new TextRange(1, Math.max(1, text.length() - 1));
if (text.length() >= begin.length()*2 && text.endsWith(begin)) {
fin -= begin.length();
}
return new TextRange(start, Math.max(1, fin));
}
}
@@ -420,4 +420,8 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
public void testResultOfIncUsed() {
doTest(new GroovyResultOfIncrementOrDecrementUsedInspection());
}
public void testNativeMapAssignability() {
doTest(new GroovyAssignabilityCheckInspection());
}
}
@@ -281,4 +281,7 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testcommandExpr$keywords() {doTest()}
public void testDiamond() {doTest()}
void testpath$stringMethodCall1() {doTest()}
void testpath$stringMethodCall2() {doTest()}
}
@@ -713,4 +713,16 @@ class Foo {
PsiReference ref = configureByFile("staticImportInSamePackage/A.groovy", "A.groovy");
assertNotNull(ref.resolve())
}
void testStringRefExpr1() {
assertNotNull(resolve("a.groovy"));
}
void testStringRefExpr2() {
assertNotNull(resolve("a.groovy"));
}
void testStringRefExpr3() {
assertNotNull(resolve("a.groovy"));
}
}
@@ -0,0 +1,5 @@
def foo(Map<String, Map<String, Object>> m) {}
foo(a:[b:'c'])
foo<warning descr="'foo' in 'NativeMapAssignability' cannot be applied to '(['a':java.lang.String])'">(a:'b')</warning>
foo<warning descr="'foo' in 'NativeMapAssignability' cannot be applied to '(['a':java.util.Map<java.lang.Integer, java.lang.Integer>])'">(a:[(2):4])</warning>
@@ -1 +1 @@
def map = [1:'d', <warning descr="Duplicate element in the map">(1)</warning>:'sd']
def map = [1:'d', <warning descr="Duplicate element in the map">1</warning>:'sd']
@@ -0,0 +1,9 @@
'foo'()
-----
Groovy script
Method call
Reference expression
PsiElement(string)(''foo'')
Arguments
PsiElement(()('(')
PsiElement())(')')
@@ -0,0 +1,18 @@
'foo'.substring(0, 1)
-----
Groovy script
Method call
Reference expression
Literal
PsiElement(string)(''foo'')
PsiElement(.)('.')
PsiElement(identifier)('substring')
Arguments
PsiElement(()('(')
Literal
PsiElement(Integer)('0')
PsiElement(,)(',')
PsiWhiteSpace(' ')
Literal
PsiElement(Integer)('1')
PsiElement())(')')
@@ -0,0 +1,3 @@
def foo(){}
'f<ref>oo'()
@@ -0,0 +1,3 @@
def foo(){}
"f<ref>oo"()
@@ -0,0 +1,3 @@
def 'foo bar'(){}
'f<ref>oo bar'()
+6
View File
@@ -86,6 +86,12 @@
<separator/>
<add-to-group group-id="SubversionFilePopupGroup" anchor="last"/>
</group>
<action id="Subversion.MarkLocallyDeletedTreeResolved" class="org.jetbrains.idea.svn.actions.MarkLocallyDeletedTreeConflictResolvedAction">
<add-to-group group-id="ChangesViewPopupMenu" anchor="after" relative-to-action="ChangesView.Diff"/>
</action>
<reference id="Subversion.MarkTreeResolved">
<add-to-group group-id="ChangesViewPopupMenu" anchor="after" relative-to-action="ChangesView.Diff"/>
</reference>
<group id="SubversionUpdateActionGroup" class="org.jetbrains.idea.svn.actions.SubversionGroup">
<reference id="Subversion.Add"/>
<reference id="ChangesView.Rollback"/>
@@ -239,6 +239,9 @@ class SvnChangeProviderContext implements StatusReceiver {
myChangelistBuilder.processChangeInList(createChange(SvnContentRevision.create(myVcs, filePath, status.getCommittedRevision()),
CurrentContentRevision.create(filePath), FileStatus.MODIFIED, status), changeListNameFromStatus(status),
SvnVcs.getKey());
} else if (status.getTreeConflict() != null) {
myChangelistBuilder.processChange(createChange(SvnContentRevision.create(myVcs, filePath, status.getCommittedRevision()),
CurrentContentRevision.create(filePath), FileStatus.MODIFIED, status), SvnVcs.getKey());
}
checkSwitched(filePath, myChangelistBuilder, status, fStatus);
}
@@ -15,8 +15,8 @@
*/
package org.jetbrains.idea.svn;
import com.intellij.openapi.vcs.changes.LocallyDeletedChange;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.LocallyDeletedChange;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -42,4 +42,8 @@ public class SvnLocallyDeletedChange extends LocallyDeletedChange {
}
return description;
}
public ConflictState getConflictState() {
return myConflictState;
}
}
@@ -0,0 +1,163 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.svn.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.BackgroundFromStartOption;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.LocallyDeletedChange;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.changes.ui.ChangesListView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.ConflictedSvnChange;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnLocallyDeletedChange;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNConflictChoice;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import java.util.Collections;
import java.util.List;
/**
* @author irengrig
* Date: 6/8/11
* Time: 4:58 PM
*/
public class MarkLocallyDeletedTreeConflictResolvedAction extends AnAction {
public MarkLocallyDeletedTreeConflictResolvedAction() {
super(SvnBundle.message("action.mark.tree.conflict.resolved.text"));
}
@Override
public void actionPerformed(AnActionEvent e) {
final MyLocallyDeletedChecker locallyDeletedChecker = new MyLocallyDeletedChecker(e);
if (! locallyDeletedChecker.isEnabled()) return;
final String markText = SvnBundle.message("action.mark.tree.conflict.resolved.confirmation.title");
final Project project = locallyDeletedChecker.getProject();
final int result = Messages.showYesNoDialog(project,
SvnBundle.message("action.mark.tree.conflict.resolved.confirmation.text"), markText,
Messages.getQuestionIcon());
if (result == DialogWrapper.OK_EXIT_CODE) {
final Ref<VcsException> exception = new Ref<VcsException>();
ProgressManager
.getInstance().run(new Task.Backgroundable(project, markText, true, BackgroundFromStartOption.getInstance()) {
public void run(@NotNull ProgressIndicator indicator) {
resolveLocallyDeletedTextConflict(locallyDeletedChecker, exception);
}
});
if (! exception.isNull()) {
AbstractVcsHelper.getInstance(project).showError(exception.get(), markText);
}
}
}
@Override
public void update(AnActionEvent e) {
final MyLocallyDeletedChecker locallyDeletedChecker = new MyLocallyDeletedChecker(e);
e.getPresentation().setVisible(locallyDeletedChecker.isEnabled());
e.getPresentation().setEnabled(locallyDeletedChecker.isEnabled());
//e.getPresentation().setText(SvnBundle.message("action.mark.tree.conflict.resolved.text"));
}
private void resolveLocallyDeletedTextConflict(MyLocallyDeletedChecker checker, Ref<VcsException> exception) {
final FilePath path = checker.getPath();
resolve(checker.getProject(), exception, path);
VcsDirtyScopeManager.getInstance(checker.getProject()).filePathsDirty(Collections.singletonList(path), null);
}
private void resolve(Project project, Ref<VcsException> exception, FilePath path) {
final SVNWCClient client = SvnVcs.getInstance(project).createWCClient();
try {
client.doResolve(path.getIOFile(), SVNDepth.EMPTY, false, false, true, SVNConflictChoice.MERGED);
}
catch (SVNException e1) {
exception.set(new VcsException(e1));
}
}
private static class MyLocallyDeletedChecker {
private final boolean myEnabled;
private final FilePath myPath;
private final Project myProject;
public MyLocallyDeletedChecker(final AnActionEvent e) {
final DataContext dc = e.getDataContext();
myProject = PlatformDataKeys.PROJECT.getData(dc);
if (myProject == null) {
myPath = null;
myEnabled = false;
return;
}
final List<LocallyDeletedChange> missingFiles = e.getData(ChangesListView.LOCALLY_DELETED_CHANGES);
if (missingFiles == null || missingFiles.size() != 1) {
final Change[] changes = e.getData(VcsDataKeys.CHANGES);
if (changes == null || changes.length != 1 || changes[0].getAfterRevision() != null) {
myPath = null;
myEnabled = false;
return;
}
myEnabled = changes[0] instanceof ConflictedSvnChange && ((ConflictedSvnChange) changes[0]).getConflictState().isTree();
if (myEnabled) {
myPath = changes[0].getBeforeRevision().getFile();
} else {
myPath = null;
}
return;
}
final LocallyDeletedChange change = missingFiles.get(0);
myEnabled = change instanceof SvnLocallyDeletedChange && ((SvnLocallyDeletedChange) change).getConflictState().isTree();
if (myEnabled) {
myPath = ((SvnLocallyDeletedChange) change).getPath();
}
else {
myPath = null;
}
}
public boolean isEnabled() {
return myEnabled;
}
public FilePath getPath() {
return myPath;
}
public Project getProject() {
return myProject;
}
}
}