Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-10-20 18:47:47 +04:00
101 changed files with 1172 additions and 857 deletions
@@ -20,12 +20,13 @@ import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.RestartAction;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.Constraints;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.IdeActions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -62,9 +63,7 @@ public class DefaultDebugUIEnvironment implements DebugUIEnvironment {
@Override
public void initActions(RunContentDescriptor content, DefaultActionGroup actionGroup) {
Executor executor = myExecutionEnvironment.getExecutor();
RestartAction restartAction = new RestartAction(content, myExecutionEnvironment);
actionGroup.add(restartAction, Constraints.FIRST);
restartAction.registerShortcut(content.getComponent());
actionGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_RERUN), Constraints.FIRST);
actionGroup.add(new CloseAction(executor, content, myExecutionEnvironment.getProject()));
actionGroup.add(new ContextHelpAction(executor.getHelpId()));
@@ -28,6 +28,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
@@ -139,6 +140,19 @@ public class PositionManagerImpl implements PositionManager {
lineNumber = -1;
}
if (psiFile instanceof PsiCompiledElement && lineNumber > -1) {
VirtualFile file = psiFile.getVirtualFile();
if (file != null) {
int[] data = file.getUserData(LINE_NUMBERS_MAPPING_KEY);
if (data != null) {
int line = mapLine(lineNumber+1, data);
if (line > -1) {
return SourcePosition.createFromLine(psiFile, line-1);
}
}
}
}
if (psiFile instanceof PsiCompiledElement || lineNumber < 0) {
final String methodSignature = location.method().signature();
if (methodSignature == null) {
@@ -165,6 +179,15 @@ public class PositionManagerImpl implements PositionManager {
return SourcePosition.createFromLine(psiFile, lineNumber);
}
private static int mapLine(int line, int[] mapping) {
for (int i = 0; i < mapping.length; i+=2) {
if (mapping[i] == line) {
return mapping[i+1];
}
}
return -1;
}
@Nullable
private PsiFile getPsiFileByLocation(final Project project, final Location location) {
if (location == null) {
@@ -136,7 +136,7 @@ public class ImportModuleAction extends AnAction {
});
StringBuilder builder = new StringBuilder("<html>Select ");
boolean first = true;
if (list.size() > 1) {
if (list.size() > 0) {
for (ProjectImportProvider provider : list) {
String sample = provider.getFileSample();
if (sample != null) {
@@ -0,0 +1,159 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.projectView;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
import com.intellij.ide.projectView.impl.ProjectViewImpl;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.Disposer;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.ui.tree.TreeUtil;
import javax.swing.tree.DefaultMutableTreeNode;
public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
private ProjectView myProjectView;
private AbstractProjectViewPSIPane myPane;
private boolean myOriginalSortByType;
private boolean myOriginalFoldersAlwaysOnTop;
@Override
public void setUp() throws Exception {
super.setUp();
myPane = new TestProjectViewPSIPane(myProject, myStructure, 9);
myPane.createComponent();
Disposer.register(myStructure, myPane);
myProjectView = ProjectView.getInstance(myProject);
myProjectView.addProjectPane(myPane);
myOriginalSortByType = myProjectView.isSortByType(myPane.getId());
myOriginalFoldersAlwaysOnTop = ((ProjectViewImpl)myProjectView).isFoldersAlwaysOnTop();
TreeUtil.expand(myPane.getTree(), 2);
}
@Override
public void tearDown() throws Exception {
myProjectView.setSortByType(myPane.getId(), myOriginalSortByType);
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(myOriginalFoldersAlwaysOnTop);
myProjectView.removeProjectPane(myPane);
super.tearDown();
}
public void testSortByName() throws Exception {
myProjectView.setSortByType(myPane.getId(), false);
assertTree("-sortByName\n" +
" a.java\n" +
" a-a.java\n" +
" a-b.java\n" +
" ab.java\n" +
" b.java\n");
}
public void testSortByType() throws Exception {
myProjectView.setSortByType(myPane.getId(), false);
assertTree("-sortByType\n" +
" a.java\n" +
" a.txt\n" +
" b.java\n" +
" b.txt\n");
myProjectView.setSortByType(myPane.getId(), true);
assertTree("-sortByType\n" +
" a.java\n" +
" b.java\n" +
" a.txt\n" +
" b.txt\n");
}
public void testFoldersOnTop() throws Exception {
// first, check with 'sort by type' disabled
myProjectView.setSortByType(myPane.getId(), false);
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(true);
assertTree("-foldersOnTop\n" +
" +b.java\n" +
" +b.txt\n" +
" a.java\n" +
" a.txt\n" +
" c.java\n" +
" c.txt\n");
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
assertTree("-foldersOnTop\n" +
" a.java\n" +
" a.txt\n" +
" +b.java\n" +
" +b.txt\n" +
" c.java\n" +
" c.txt\n");
// now let's check the behavior, when sortByType is enabled
myProjectView.setSortByType(myPane.getId(), true);
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(true);
assertTree("-foldersOnTop\n" +
" +b.java\n" +
" +b.txt\n" +
" a.java\n" +
" c.java\n" +
" a.txt\n" +
" c.txt\n");
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
assertTree("-foldersOnTop\n" +
" a.java\n" +
" c.java\n" +
" a.txt\n" +
" c.txt\n" +
" +b.java\n" +
" +b.txt\n");
}
public void testSortByTypeBetweenFilesAndFolders() throws Exception {
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
myProjectView.setSortByType(myPane.getId(), false);
assertTree("-sortByTypeBetweenFilesAndFolders\n" +
" a.java\n" +
" +a.java_folder\n" +
" a.txt\n" +
" +a_folder\n" +
" b.java\n" +
" +b.java_folder\n" +
" b.txt\n" +
" +b_folder\n");
myProjectView.setSortByType(myPane.getId(), true);
assertTree("-sortByTypeBetweenFilesAndFolders\n" +
" a.java\n" +
" b.java\n" +
" a.txt\n" +
" b.txt\n" +
" +a.java_folder\n" +
" +a_folder\n" +
" +b.java_folder\n" +
" +b_folder\n");
}
private void assertTree(String expected) {
DefaultMutableTreeNode element = myPane.getTreeBuilder().getNodeForElement(getContentDirectory());
assertNotNull("Element for " + getContentDirectory() + " not found", element);
assertEquals(expected, PlatformTestUtil.print(myPane.getTree(), element, new Queryable.PrintInfo(), false));
}
}
@@ -129,16 +129,28 @@ public class Main {
// always delete previous patch copy
File patchCopy = new File(tempDir, patchFileName + "_copy");
File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy)) {
File jnaUtilsCopy = new File(tempDir, "jna-utils.jar." + platform + "_copy");
File jnaCopy = new File(tempDir, "jna.jar." + platform + "_copy");
if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy) || !FileUtilRt.delete(jnaUtilsCopy) || !FileUtilRt.delete(jnaCopy)) {
throw new IOException("Cannot delete temporary files in " + tempDir);
}
File patch = new File(tempDir, patchFileName);
if (!patch.exists()) return;
File log4j = new File(PathManager.getLibPath(), "log4j.jar");
if (!log4j.exists()) throw new IOException("Log4J missing: " + log4j);
if (!log4j.exists()) throw new IOException("Log4J is missing: " + log4j);
File jnaUtils = new File(PathManager.getLibPath(), "jna-utils.jar");
if (!jnaUtils.exists()) throw new IOException("jna-utils.jar is missing: " + jnaUtils);
File jna = new File(PathManager.getLibPath(), "jna.jar");
if (!jna.exists()) throw new IOException("jna is missing: " + jna);
copyFile(patch, patchCopy, true);
copyFile(log4j, log4jCopy, false);
copyFile(jna, jnaCopy, false);
copyFile(jnaUtils, jnaUtilsCopy, false);
int status = 0;
if (Restarter.isSupported()) {
@@ -154,7 +166,7 @@ public class Main {
System.getProperty("java.home") + "/bin/java",
"-Xmx500m",
"-classpath",
patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath(),
patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath() + File.pathSeparator + jnaCopy.getPath() + File.pathSeparator + jnaUtilsCopy.getPath(),
"-Djava.io.tmpdir=" + tempDir,
"-Didea.updater.log=" + PathManager.getLogPath(),
"-Dswing.defaultlaf=" + UIManager.getSystemLookAndFeelClassName(),
@@ -31,7 +31,9 @@ import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.TimeoutUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -536,4 +538,14 @@ public class PsiUtilCore {
}
});
}
@Contract("null -> null;!null -> !null")
public static IElementType getElementType(@Nullable ASTNode node) {
return node == null ? null : node.getElementType();
}
@Contract("null -> null;!null -> !null")
public static IElementType getElementType(@Nullable PsiElement element) {
return element == null ? null : getElementType(element.getNode());
}
}
@@ -18,6 +18,7 @@ package com.intellij.dvcs.push.ui;
import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkHtmlRenderer;
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.vcs.log.VcsFullCommitDetails;
@@ -41,8 +42,9 @@ public class CommitNode extends DefaultMutableTreeNode implements CustomRendered
@Override
public void render(@NotNull ColoredTreeCellRenderer renderer) {
String subject = getUserObject().getSubject();
renderer.append(subject, SimpleTextAttributes.REGULAR_ATTRIBUTES);
new IssueLinkRenderer(myProject, renderer).appendTextWithLinks(getUserObject().getSubject(),
new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER,
renderer.getForeground()));
}
public String getTooltip() {
@@ -15,13 +15,11 @@
*/
package com.intellij.dvcs.push.ui;
import com.intellij.dvcs.push.PushTargetPanel;
import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
import com.intellij.ui.CheckboxTree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.MouseEvent;
public class VcsBranchEditorListener extends LinkMouseListenerBase {
@@ -31,18 +29,6 @@ public class VcsBranchEditorListener extends LinkMouseListenerBase {
myRenderer = renderer;
}
@Override
public void mouseMoved(MouseEvent e) {
Component component = (Component)e.getSource();
Object tag = getTagAt(e);
if (tag instanceof PushTargetPanel || tag instanceof TextWithLinkNode || tag instanceof ExtraEditControl) {
component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
else {
component.setCursor(Cursor.getDefaultCursor());
}
}
@Nullable
@Override
protected Object getTagAt(@NotNull final MouseEvent e) {
@@ -512,7 +512,7 @@ public class CommentByLineCommentHandler extends MultiCaretCodeInsightActionHand
if (startOffset == endOffset) {
return;
}
RangeMarker marker = block.editor.getDocument().createRangeMarker(startOffset, endOffset);
RangeMarker marker = endOffset > startOffset ? block.editor.getDocument().createRangeMarker(startOffset, endOffset) : null;
String prefix = commenter.getLineCommentPrefix();
if (prefix != null) {
CharSequence chars = document.getCharsSequence();
@@ -581,7 +581,9 @@ public class CommentByLineCommentHandler extends MultiCaretCodeInsightActionHand
for (int i = prefixes.size() - 1; i >= 0; i--) {
uncommentRange(document, startOffset + prefixes.get(i), Math.min(startOffset + suffixes.get(i) + suffix.length(), endOffset), commenter);
}
CommentByBlockCommentHandler.processDocument(document, marker, commenter, false);
if (marker != null) {
CommentByBlockCommentHandler.processDocument(document, marker, commenter, false);
}
}
private static void commentLine(Block block, int line, int offset) {
@@ -56,6 +56,7 @@ import org.jetbrains.annotations.Nullable;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.io.*;
import java.util.List;
@@ -75,6 +76,7 @@ public class ConsoleHistoryController {
private final AnAction myHistoryPrev = new MyAction(false);
private final AnAction myBrowseHistory = new MyBrowseAction();
private boolean myMultiline;
private boolean isStandardUpDownUsed = false;
private final ModelHelper myHelper;
private long myLastSaveStamp;
@@ -115,6 +117,7 @@ public class ConsoleHistoryController {
loadHistory(myHelper.getId());
}
configureActions();
isStandardUpDownUsed = checkIfStandardUpDownUsed();
myLastSaveStamp = getCurrentTimeStamp();
}
@@ -122,21 +125,18 @@ public class ConsoleHistoryController {
return getModel().getModificationCount() + myConsole.getEditorDocument().getModificationStamp();
}
private void configureActions() {
private boolean checkIfStandardUpDownUsed() {
return isShortcutSetsIntersect(myHistoryNext.getShortcutSet(), getShortcutUpDown(true))
|| isShortcutSetsIntersect(myHistoryPrev.getShortcutSet(), getShortcutUpDown(false));
}
protected void configureActions() {
EmptyAction.setupAction(myHistoryNext, "Console.History.Next", null);
EmptyAction.setupAction(myHistoryPrev, "Console.History.Previous", null);
EmptyAction.setupAction(myBrowseHistory, "Console.History.Browse", null);
if (!myMultiline) {
AnAction up = ActionManager.getInstance().getActionOrStub(IdeActions.ACTION_EDITOR_MOVE_CARET_UP);
AnAction down = ActionManager.getInstance().getActionOrStub(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
if (up != null && down != null) {
myHistoryNext.registerCustomShortcutSet(up.getShortcutSet(), null);
myHistoryPrev.registerCustomShortcutSet(down.getShortcutSet(), null);
}
else {
myHistoryNext.registerCustomShortcutSet(KeyEvent.VK_UP, 0, null);
myHistoryPrev.registerCustomShortcutSet(KeyEvent.VK_DOWN, 0, null);
}
myHistoryNext.registerCustomShortcutSet(getShortcutUpDown(true), null);
myHistoryPrev.registerCustomShortcutSet(getShortcutUpDown(false), null);
}
myHistoryNext.registerCustomShortcutSet(myHistoryNext.getShortcutSet(), myConsole.getCurrentEditor().getComponent());
myHistoryPrev.registerCustomShortcutSet(myHistoryPrev.getShortcutSet(), myConsole.getCurrentEditor().getComponent());
@@ -263,7 +263,7 @@ public class ConsoleHistoryController {
@Override
public void update(final AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabled(myMultiline || canMoveInEditor(myNext));
e.getPresentation().setEnabled(!isStandardUpDownUsed || canMoveInEditor(myNext));
}
}
@@ -505,4 +505,29 @@ public class ConsoleHistoryController {
out.endTag(null, tag);
}
}
private static ShortcutSet getShortcutUpDown(boolean isUp) {
AnAction action = ActionManager.getInstance().getActionOrStub(isUp ?
IdeActions.ACTION_EDITOR_MOVE_CARET_UP :
IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
if (action != null) {
return action.getShortcutSet();
}
return new CustomShortcutSet(KeyStroke.getKeyStroke(isUp ? KeyEvent.VK_UP : KeyEvent.VK_DOWN, 0));
}
private static boolean isShortcutSetsIntersect(ShortcutSet set1, ShortcutSet set2) {
final Shortcut[] shortcuts1 = set1.getShortcuts();
final Shortcut[] shortcuts2 = set2.getShortcuts();
for (Shortcut s1 : shortcuts1) {
for (Shortcut s2 : shortcuts2) {
if (s1.equals(s2)) {
return true;
}
}
}
return false;
}
}
@@ -253,31 +253,8 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
consoleExecuteActionHandler);
}
@SuppressWarnings("UnusedDeclaration")
@Deprecated
/**
* @deprecated to remove in IDEA 14
*/
public static AnAction createConsoleExecAction(LanguageConsoleImpl languageConsole,
ProcessHandler processHandler,
@SuppressWarnings("deprecation") ConsoleExecuteActionHandler consoleExecuteActionHandler) {
return ConsoleExecuteAction.createAction(languageConsole, consoleExecuteActionHandler);
}
@NotNull
protected ProcessBackedConsoleExecuteActionHandler createExecuteActionHandler() {
//noinspection deprecation
return createConsoleExecuteActionHandler();
}
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
@Deprecated
/**
* @deprecated to remove in IDEA 14
*/
protected ConsoleExecuteActionHandler createConsoleExecuteActionHandler() {
throw new AbstractMethodError();
}
protected abstract ProcessBackedConsoleExecuteActionHandler createExecuteActionHandler();
public T getConsoleView() {
return myConsoleView;
@@ -1,11 +0,0 @@
package com.intellij.execution.runners;
@Deprecated
/**
* @deprecated to remove in IDEA 15
*/
public abstract class BaseConsoleExecuteActionHandler extends com.intellij.execution.console.BaseConsoleExecuteActionHandler {
public BaseConsoleExecuteActionHandler(boolean preserveMarkup) {
super(preserveMarkup);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,26 +26,12 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.project.DumbAware;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author Roman.Chernyatchik
*/
class FakeRerunAction extends AnAction implements DumbAware {
@SuppressWarnings("deprecation")
static final List<RestartAction> registry = ContainerUtil.createLockFreeCopyOnWriteList();
@Override
public void update(AnActionEvent event) {
public void update(@NotNull AnActionEvent event) {
Presentation presentation = event.getPresentation();
ExecutionEnvironment environment = getEnvironment(event);
if (environment != null) {
@@ -55,22 +41,14 @@ class FakeRerunAction extends AnAction implements DumbAware {
return;
}
FakeRerunAction action = findActualAction(event);
presentation.setEnabled(action != null && action.isEnabled(event));
presentation.setVisible(false);
presentation.setEnabledAndVisible(false);
}
@Override
public void actionPerformed(AnActionEvent event) {
public void actionPerformed(@NotNull AnActionEvent event) {
ExecutionEnvironment environment = getEnvironment(event);
if (environment != null) {
ExecutionUtil.restart(environment);
return;
}
FakeRerunAction action = findActualAction(event);
if (action != null && action.isEnabled(event)) {
action.actionPerformed(event);
}
}
@@ -92,50 +70,4 @@ class FakeRerunAction extends AnAction implements DumbAware {
!ExecutorRegistry.getInstance().isStarting(environment) &&
!(processHandler != null && processHandler.isProcessTerminating());
}
@Nullable
private JComponent getRunComponent(@NotNull AnActionEvent event) {
RunContentDescriptor descriptor = getDescriptor(event);
return descriptor == null ? null : descriptor.getComponent();
}
@Nullable
private static FakeRerunAction findActualAction(@NotNull final AnActionEvent event) {
if (registry.isEmpty()) {
return null;
}
List<FakeRerunAction> candidates = new ArrayList<FakeRerunAction>(registry);
Collections.sort(candidates, new Comparator<FakeRerunAction>() {
@Override
public int compare(@NotNull FakeRerunAction action1, @NotNull FakeRerunAction action2) {
boolean isActive1 = action1.isEnabled(event);
if (isActive1 != action2.isEnabled(event)) {
return isActive1 ? -1 : 1;
}
JComponent component1 = action1.getRunComponent(event);
JComponent component2 = action2.getRunComponent(event);
Window window1 = component1 == null ? null : SwingUtilities.windowForComponent(component1);
Window window2 = component2 == null ? null : SwingUtilities.windowForComponent(component2);
if (window1 == null) {
return 1;
}
if (window2 == null) {
return -1;
}
boolean showing1 = component1.isShowing();
boolean showing2 = component2.isShowing();
if (showing1 && !showing2) {
return -1;
}
if (showing2 && !showing1) {
return 1;
}
return (window1.isActive() ? -1 : 1);
}
});
return candidates.get(0);
}
}
@@ -1,84 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.runners;
import com.intellij.execution.Executor;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@Deprecated
/**
* to remove in IDEA 15
*/
public class RestartAction extends FakeRerunAction implements DumbAware, AnAction.TransparentUpdate, Disposable {
private final RunContentDescriptor myDescriptor;
private final ExecutionEnvironment myEnvironment;
public RestartAction(@NotNull RunContentDescriptor descriptor, @NotNull ExecutionEnvironment environment) {
//noinspection deprecation
this(environment.getExecutor(), null, descriptor, environment);
}
@Deprecated
/**
* @deprecated environment must provide runner id
* to remove in IDEA 15
*/
public RestartAction(@SuppressWarnings("UnusedParameters") @NotNull Executor executor,
@Nullable ProgramRunner runner,
@NotNull RunContentDescriptor descriptor,
@NotNull ExecutionEnvironment environment) {
Disposer.register(descriptor, this);
FakeRerunAction.registry.add(this);
myEnvironment = runner == null ? environment : RunContentBuilder.fix(environment, runner);
getTemplatePresentation().setEnabled(false);
myDescriptor = descriptor;
}
@Override
public void dispose() {
FakeRerunAction.registry.remove(this);
}
@Override
@NotNull
protected RunContentDescriptor getDescriptor(AnActionEvent event) {
return myDescriptor;
}
@Override
@NotNull
protected ExecutionEnvironment getEnvironment(AnActionEvent event) {
return myEnvironment;
}
public void registerShortcut(JComponent component) {
registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_RERUN)),
component);
}
}
@@ -63,9 +63,12 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
if (descriptor1 instanceof ProjectViewNode && descriptor2 instanceof ProjectViewNode) {
final Project project = descriptor1.getProject();
final ProjectView projectView = ProjectView.getInstance(project);
if (!(projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop())) {
ProjectViewNode node1 = (ProjectViewNode)descriptor1;
ProjectViewNode node2 = (ProjectViewNode)descriptor2;
ProjectViewNode node1 = (ProjectViewNode)descriptor1;
ProjectViewNode node2 = (ProjectViewNode)descriptor2;
boolean isFoldersOnTop = !(projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop());
if (isFoldersOnTop) {
int typeWeight1 = node1.getTypeSortWeight(isSortByType());
int typeWeight2 = node2.getTypeSortWeight(isSortByType());
if (typeWeight1 != 0 && typeWeight2 == 0) {
@@ -77,30 +80,34 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
if (typeWeight1 != 0 && typeWeight2 != typeWeight1) {
return typeWeight1 - typeWeight2;
}
if (isSortByType()) {
final Comparable typeSortKey1 = node1.getTypeSortKey();
final Comparable typeSortKey2 = node2.getTypeSortKey();
if (typeSortKey1 != null && typeSortKey2 != null) {
final int result = typeSortKey1.compareTo(typeSortKey2);
if (result != 0) return result;
}
}
if (isSortByType()) {
final Comparable typeSortKey1 = node1.getTypeSortKey();
final Comparable typeSortKey2 = node2.getTypeSortKey();
if (!(typeSortKey1 == null && typeSortKey2 == null)) {
if (typeSortKey1 == null) return 1;
if (typeSortKey2 == null) return -1;
//noinspection unchecked
final int result = typeSortKey1.compareTo(typeSortKey2);
if (result != 0) return result;
}
else {
final Comparable typeSortKey1 = node1.getSortKey();
final Comparable typeSortKey2 = node2.getSortKey();
if (typeSortKey1 != null && typeSortKey2 != null) {
final int result = typeSortKey1.compareTo(typeSortKey2);
if (result != 0) return result;
}
}
else {
final Comparable typeSortKey1 = node1.getSortKey();
final Comparable typeSortKey2 = node2.getSortKey();
if (typeSortKey1 != null && typeSortKey2 != null) {
//noinspection unchecked
final int result = typeSortKey1.compareTo(typeSortKey2);
if (result != 0) return result;
}
}
if (isAbbreviateQualifiedNames()) {
String key1 = node1.getQualifiedNameSortKey();
String key2 = node2.getQualifiedNameSortKey();
if (key1 != null && key2 != null) {
return key1.compareToIgnoreCase(key2);
}
if (isAbbreviateQualifiedNames()) {
String key1 = node1.getQualifiedNameSortKey();
String key2 = node2.getQualifiedNameSortKey();
if (key1 != null && key2 != null) {
return key1.compareToIgnoreCase(key2);
}
}
}
@@ -119,5 +126,4 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
private boolean isAbbreviateQualifiedNames() {
return myProjectView != null && myProjectView.isAbbreviatePackageNames(myPaneId);
}
}
@@ -125,7 +125,7 @@
<properties>
<opaque value="true"/>
</properties>
<border type="etched"/>
<border type="none"/>
<children>
<component id="61c42" class="javax.swing.JLabel">
<constraints>
@@ -24,30 +24,27 @@ import javax.swing.plaf.FontUIResource;
/**
* @author Sergey.Malenkov
*/
public final class RelativeFont implements PropertyChangeListener {
private static final String PROPERTY = "font";
public enum RelativeFont implements PropertyChangeListener {
PLAIN(Font.PLAIN, 0),
BOLD(Font.BOLD, 0),
LARGE(1f),
SMALL(-1f),
HUGE(2f),
TINY(-2f);
public static final RelativeFont PLAIN = new RelativeFont(Font.PLAIN, 0);
public static final RelativeFont BOLD = new RelativeFont(Font.BOLD, 0);
public static final RelativeFont LARGE = new RelativeFont(1f);
public static final RelativeFont SMALL = new RelativeFont(-1f);
public static final RelativeFont HUGE = new RelativeFont(2f);
public static final RelativeFont TINY = new RelativeFont(-2f);
private static final String PROPERTY = "font";
private final int myStyle;
private final float mySize;
public RelativeFont(float size) {
RelativeFont(float size) {
this.myStyle = -1;
this.mySize = size;
}
public RelativeFont(int style, float size) {
RelativeFont(int style, float size) {
this.myStyle = style & (Font.BOLD | Font.ITALIC);
this.mySize = size;
if (style != myStyle) {
throw new IllegalArgumentException("style");
}
}
public <T extends Component> T install(T component) {
@@ -112,12 +112,12 @@ public final class HorizontalLayout implements LayoutManager2 {
@Override
public void addLayoutComponent(String name, Component component) {
synchronized (component.getTreeLock()) {
if (name == null || CENTER.equalsIgnoreCase(name)) {
myCenter.add(component);
}
else if (LEFT.equalsIgnoreCase(name)) {
if (name == null || LEFT.equalsIgnoreCase(name)) {
myLeft.add(component);
}
else if (CENTER.equalsIgnoreCase(name)) {
myCenter.add(component);
}
else if (RIGHT.equalsIgnoreCase(name)) {
myRight.add(component);
}
@@ -242,7 +242,7 @@ public final class HorizontalLayout implements LayoutManager2 {
if (result == null) {
result = new Dimension();
}
else if (aligned) {
else if (aligned && center != null) {
int leftWidth = left == null ? 0 : left.width;
int rightWidth = right == null ? 0 : right.width;
result.width += Math.abs(leftWidth - rightWidth);
@@ -112,12 +112,12 @@ public final class VerticalLayout implements LayoutManager2 {
@Override
public void addLayoutComponent(String name, Component component) {
synchronized (component.getTreeLock()) {
if (name == null || CENTER.equalsIgnoreCase(name)) {
myCenter.add(component);
}
else if (TOP.equalsIgnoreCase(name)) {
if (name == null || TOP.equalsIgnoreCase(name)) {
myTop.add(component);
}
else if (CENTER.equalsIgnoreCase(name)) {
myCenter.add(component);
}
else if (BOTTOM.equalsIgnoreCase(name)) {
myBottom.add(component);
}
@@ -242,7 +242,7 @@ public final class VerticalLayout implements LayoutManager2 {
if (result == null) {
result = new Dimension();
}
else if (aligned) {
else if (aligned && center != null) {
int topHeight = top == null ? 0 : top.height;
int bottomHeight = bottom == null ? 0 : bottom.height;
result.width += Math.abs(topHeight - bottomHeight);
@@ -42,11 +42,12 @@ import java.util.Arrays;
public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
public static final int FULL_DIFF_DIVIDER_POLYGONS_OFFSET = 3;
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.external.DiffManagerImpl");
private static final Logger LOG = Logger.getInstance(DiffManagerImpl.class);
private static final Externalizer<String> TOOL_PATH_UPDATE = new Externalizer<String>() {
@NonNls private static final String NEW_VALUE = "newValue";
@Override
public String readValue(Element dataElement) {
String path = dataElement.getAttributeValue(NEW_VALUE);
if (path != null) return path;
@@ -54,6 +55,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
return prevValue != null ? prevValue.trim() : null;
}
@Override
public void writeValue(Element dataElement, String path) {
dataElement.setAttribute(VALUE_ATTRIBUTE, path);
dataElement.setAttribute(NEW_VALUE, path);
@@ -75,6 +77,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
public static final Key<Boolean> EDITOR_IS_DIFF_KEY = new Key<Boolean>("EDITOR_IS_DIFF_KEY");
private static final MarkupEditorFilter DIFF_EDITOR_FILTER = new MarkupEditorFilter() {
@Override
public boolean avaliableIn(Editor editor) {
return DiffUtil.isDiffEditor(editor);
}
@@ -96,8 +99,10 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
myProperties.registerProperty(MERGE_TOOL_PARAMETERS);
}
@Override
public DiffTool getIdeaDiffTool() { return INTERNAL_DIFF; }
@Override
public DiffTool getDiffTool() {
DiffTool[] standardTools;
// there is inner check in multiple tool for external viewers as well
@@ -131,21 +136,25 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
return new CompositeDiffTool(allTools);
}
@Override
public boolean registerDiffTool(@NotNull DiffTool tool) throws NullPointerException {
if (myAdditionTools.contains(tool)) return false;
myAdditionTools.add(tool);
return true;
}
@Override
public void unregisterDiffTool(DiffTool tool) {
myAdditionTools.remove(tool);
LOG.assertTrue(!myAdditionTools.contains(tool));
}
@Override
public MarkupEditorFilter getDiffEditorFilter() {
return DIFF_EDITOR_FILTER;
}
@Override
public DiffPanel createDiffPanel(Window window, Project project, DiffTool parentTool) {
return new DiffPanelImpl(window, project, true, true, FULL_DIFF_DIVIDER_POLYGONS_OFFSET, parentTool);
}
@@ -161,6 +170,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
return (DiffManagerImpl)DiffManager.getInstance();
}
@Override
public void readExternal(@NotNull Element element) throws InvalidDataException {
myProperties.readExternal(element);
readPolicy(element);
@@ -191,6 +201,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
}
}
@Override
public void writeExternal(@NotNull Element element) throws WriteExternalException {
myProperties.writeExternal(element);
if (myComparisonPolicy != null) {
@@ -66,9 +66,9 @@ final class Banner extends JPanel {
}
else {
if (i > 0) {
myLeftPanel.add(HorizontalLayout.LEFT, RelativeFont.HUGE.install(new JLabel("\u203A")));
myLeftPanel.add(RelativeFont.HUGE.install(new JLabel("\u203A")));
}
myLeftPanel.add(HorizontalLayout.LEFT, RelativeFont.BOLD.install(new JLabel(name)));
myLeftPanel.add(RelativeFont.BOLD.install(new JLabel(name)));
}
i += 2;
}
@@ -69,7 +69,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
private static final String NODE_ICON = "settings.tree.view.icon";
private static final Color WRONG_CONTENT = JBColor.RED;
private static final Color MODIFIED_CONTENT = JBColor.BLUE;
public static final Color FOREGROUND = new JBColor(0x1A1A1A, 0xBBBBBB);
public static final Color FOREGROUND = new JBColor(Gray.x1A, Gray.xBB);
public static final Color BACKGROUND = new JBColor(0xE6EBF0, 0x3E434C);
final SimpleTree myTree;
@@ -97,7 +97,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
TreeUtil.installActions(myTree);
myTree.setOpaque(true);
myTree.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
@@ -116,6 +115,8 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
mySeparator = new JLabel();
mySeparator.setForeground(FOREGROUND);
mySeparator.setIconTextGap(10);
mySeparator.setBorder(BorderFactory.createEmptyBorder(1, 19, 0, 0));
myTree.addComponentListener(new ComponentAdapter() {
@Override
@@ -273,10 +274,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
return; // separator is not needed without scrolling
}
mySeparator.setFont(myTree.getFont());
mySeparator.setIcon(myTree.getEmptyHandle());
int height = mySeparator.getPreferredSize().height;
String group = findGroupNameAt(0, height);
String group = findGroupNameAt(0, height + 3);
if (group != null && group.equals(findGroupNameAt(0, 0))) {
mySeparator.setBorder(BorderFactory.createEmptyBorder(1, 22, 0, 0));
mySeparator.setText(group);
Rectangle bounds = myScroller.getViewport().getBounds();
@@ -459,16 +460,16 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
private final class MyRenderer extends JPanel implements TreeCellRenderer {
private final JLabel myTextLabel = new ErrorLabel();
private final JLabel myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
private final JLabel myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
private final JLabel myNodeIcon = new JLabel();
private final JLabel myProjectIcon = new JLabel();
public MyRenderer() {
super(new BorderLayout());
super(new BorderLayout(10, 0));
myNodeIcon.setName(NODE_ICON);
add(BorderLayout.CENTER, myTextLabel);
add(BorderLayout.WEST, myNodeIcon);
add(BorderLayout.EAST, myProjectIcon);
setBorder(BorderFactory.createEmptyBorder(1, 0, 3, 0));
setBorder(BorderFactory.createEmptyBorder(1, 10, 3, 10));
}
public Component getTreeCellRendererComponent(JTree tree,
@@ -554,9 +555,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myNodeIcon.setIcon(nodeIcon);
// calculate minimum size
if (node != null && tree.isVisible()) {
int width = getPreferredSize().width;
width += node.myLevel * UIUtil.getTreeLeftChildIndent();
width += node.myLevel * UIUtil.getTreeRightChildIndent();
int width = 10 * node.myLevel + getPreferredSize().width;
Insets insets = tree.getInsets();
if (insets != null) {
width += insets.left + insets.right;
@@ -722,19 +721,21 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
boolean hasBeenExpanded,
boolean isLeaf) {
if (tree != null) {
int width = tree.getWidth();
bounds.width = tree.getWidth();
Container parent = tree.getParent();
if (parent instanceof JViewport) {
JViewport viewport = (JViewport)parent;
width = viewport.getWidth() - viewport.getViewPosition().x;
}
width -= bounds.x;
if (bounds.width < width) {
bounds.width = width;
bounds.width = viewport.getWidth() - viewport.getViewPosition().x;
}
bounds.width -= bounds.x;
}
super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf);
}
@Override
protected int getRowX(int row, int depth) {
return 10 * depth;
}
}
private final class MyBuilder extends FilteringTreeBuilder {
@@ -43,6 +43,7 @@ import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
import com.intellij.ui.*;
import com.intellij.ui.components.labels.ActionLink;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.util.PlatformUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -171,7 +172,7 @@ public class FlatWelcomeFrame extends JFrame implements WelcomeFrameProvider, Id
@Override
public IdeFrame createFrame() {
return Registry.is("ide.new.welcome.screen") ? this : null;
return Registry.is("ide.new.welcome.screen") && (PlatformUtils.isIntelliJ() || PlatformUtils.isCidr()) ? this : null;
}
private class FlatWelcomeScreen extends JPanel implements WelcomeScreen {
@@ -328,7 +329,7 @@ public class FlatWelcomeFrame extends JFrame implements WelcomeFrameProvider, Id
private JComponent createRecentProjects() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(new NewRecentProjectPanel(this), BorderLayout.NORTH);
panel.add(new NewRecentProjectPanel(this), BorderLayout.CENTER);
panel.setBackground(getProjectsBackGround());
return panel;
}
@@ -1379,9 +1379,9 @@ action.MarkAsOriginalTypeAction.text=Mark as
action.Console.Execute.text=Execute Current Statement
action.Console.Execute.description=Execute current statement in console
action.Console.History.Previous.text=Previous
action.Console.History.Previous.text=Previous history entry
action.Console.History.Previous.description=Previous console history entry
action.Console.History.Next.text=Next
action.Console.History.Next.text=Next history entry
action.Console.History.Next.description=Next console history entry
action.Console.History.Browse.text=Browse History
action.Console.History.Browse.description=Browse console history
@@ -295,4 +295,5 @@ exportable.CodeFoldingSettings.presentable.name=Code Folding
exportable.XmlFoldingSettings.presentable.name=XML Code Folding
exportable.XmlSettings.presentable.name=XML
exportable.PlaybackDebugger.presentable.name=Playback Debugger
exportable.XmlEditorOptions.presentable.name=XML Editor
exportable.XmlEditorOptions.presentable.name=XML Editor
exportable.BuiltInServerOptions.presentable.name=Built-in server
@@ -537,9 +537,8 @@
<customPortServerManager implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$MyCustomPortServerManager"/>
<xdebugger.configurableProvider implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$BuiltInServerDebuggerConfigurableProvider"/>
<exportable serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
<applicationService serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions" serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
<projectService serviceInterface="org.jetbrains.builtInWebServer.WebServerPathToFileManager" serviceImplementation="org.jetbrains.builtInWebServer.WebServerPathToFileManager"/>
<applicationService serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
<projectService serviceImplementation="org.jetbrains.builtInWebServer.WebServerPathToFileManager"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains">
<urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
@@ -631,7 +631,12 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
}
catch (Throwable e) {
CompositeException result = new CompositeException(e);
disposeProject(result);
try {
tearDown();
}
catch (Throwable th) {
result.add(th);
}
throw result;
}
try {
@@ -121,12 +121,23 @@ public class PlatformTestUtil {
}
public static String print(JTree tree, boolean withSelection) {
return print(tree, withSelection, null);
return print(tree, tree.getModel().getRoot(), withSelection, null, null);
}
public static String print(JTree tree, Object root, @Nullable Queryable.PrintInfo printInfo, boolean withSelection) {
return print(tree, root, withSelection, printInfo, null);
}
public static String print(JTree tree, boolean withSelection, @Nullable Condition<String> nodePrintCondition) {
return print(tree, tree.getModel().getRoot(), withSelection, null, nodePrintCondition);
}
public static String print(JTree tree, Object root,
boolean withSelection,
@Nullable Queryable.PrintInfo printInfo,
@Nullable Condition<String> nodePrintCondition) {
StringBuilder buffer = new StringBuilder();
final Collection<String> strings = printAsList(tree, withSelection, nodePrintCondition);
final Collection<String> strings = printAsList(tree, root, withSelection, printInfo, nodePrintCondition);
for (String string : strings) {
buffer.append(string).append("\n");
}
@@ -134,9 +145,15 @@ public class PlatformTestUtil {
}
public static Collection<String> printAsList(JTree tree, boolean withSelection, @Nullable Condition<String> nodePrintCondition) {
return printAsList(tree, tree.getModel().getRoot(), withSelection, null, nodePrintCondition);
}
private static Collection<String> printAsList(JTree tree, Object root,
boolean withSelection,
@Nullable Queryable.PrintInfo printInfo,
Condition<String> nodePrintCondition) {
Collection<String> strings = new ArrayList<String>();
Object root = tree.getModel().getRoot();
printImpl(tree, root, strings, 0, withSelection, nodePrintCondition);
printImpl(tree, root, strings, 0, withSelection, printInfo, nodePrintCondition);
return strings;
}
@@ -145,13 +162,14 @@ public class PlatformTestUtil {
Collection<String> strings,
int level,
boolean withSelection,
@Nullable Queryable.PrintInfo printInfo,
@Nullable Condition<String> nodePrintCondition) {
DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)root;
final Object userObject = defaultMutableTreeNode.getUserObject();
String nodeText;
if (userObject != null) {
nodeText = toString(userObject, null);
nodeText = toString(userObject, printInfo);
}
else {
nodeText = "null";
@@ -183,7 +201,7 @@ public class PlatformTestUtil {
int childCount = tree.getModel().getChildCount(root);
if (expanded) {
for (int i = 0; i < childCount; i++) {
printImpl(tree, tree.getModel().getChild(root, i), strings, level + 1, withSelection, nodePrintCondition);
printImpl(tree, tree.getModel().getChild(root, i), strings, level + 1, withSelection, printInfo, nodePrintCondition);
}
}
}
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.issueLinks;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vcs.IssueNavigationConfiguration;
import com.intellij.ui.JBColor;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Consumer;
@@ -84,7 +85,6 @@ public class IssueLinkRenderer {
}
private static SimpleTextAttributes getLinkAttributes(final SimpleTextAttributes baseStyle) {
return (baseStyle.getStyle() & SimpleTextAttributes.STYLE_BOLD) != 0 ?
SimpleTextAttributes.LINK_BOLD_ATTRIBUTES : SimpleTextAttributes.LINK_ATTRIBUTES;
return new SimpleTextAttributes(baseStyle.getStyle() | SimpleTextAttributes.STYLE_UNDERLINE, JBColor.blue);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.siyeh.ig.cloneable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -67,6 +68,9 @@ public class CloneInNonCloneableClassInspection extends BaseInspection {
if (CloneUtils.isCloneable(containingClass)) {
return;
}
if (method.hasModifierProperty(PsiModifier.FINAL) && CloneUtils.onlyThrowsCloneNotSupportedException(method)) {
return;
}
registerMethodError(method, containingClass);
}
}
@@ -74,9 +74,8 @@ public class CloneUtils {
if (!(statement instanceof PsiThrowStatement)) {
return false;
}
final PsiThrowStatement throwStatement =
(PsiThrowStatement)statement;
final PsiExpression exception = throwStatement.getException();
final PsiThrowStatement throwStatement = (PsiThrowStatement)statement;
final PsiExpression exception = ParenthesesUtils.stripParentheses(throwStatement.getException());
if (!(exception instanceof PsiNewExpression)) {
return false;
}
@@ -21,8 +21,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorSettings;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
@@ -105,24 +104,11 @@ public class ProblematicWhitespaceInspection extends BaseInspection {
private static class ProblematicWhitespaceVisitor extends BaseInspectionVisitor {
private static boolean isLanguageFileType(FileType fileType) {
return (fileType != StdFileTypes.GUI_DESIGNER_FORM) &&
(fileType != StdFileTypes.IDEA_MODULE) &&
(fileType != StdFileTypes.IDEA_PROJECT) &&
(fileType != StdFileTypes.IDEA_WORKSPACE) &&
(fileType != FileTypes.ARCHIVE) &&
(fileType != FileTypes.UNKNOWN) &&
(fileType != FileTypes.PLAIN_TEXT) &&
//!(fileType instanceof AbstractFileType) && // not sure about this one
!fileType.isBinary() &&
!fileType.isReadOnly();
}
@Override
public void visitFile(PsiFile file) {
super.visitFile(file);
final FileType fileType = file.getFileType();
if (!isLanguageFileType(fileType)) {
if (!(fileType instanceof LanguageFileType)) {
return;
}
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
@@ -1,15 +0,0 @@
package com.siyeh.igtest.cloneable;
public class CloneCallsConstructorInspection implements Cloneable
{
public void foo()
{
}
public Object clone()
{
return new CloneCallsConstructorInspection();
}
}
@@ -0,0 +1,13 @@
public class CloneInNonCloneableClass {
public final Object clone() throws CloneNotSupportedException {
// don't warn on final method that only throws CloneNotSupportedException
throw new CloneNotSupportedException();
}
}
class AB {
@Override
protected Object <warning descr="'clone()' defined in non-Cloneable class 'AB'">clone</warning>() throws CloneNotSupportedException {
return super.clone();
}
}
@@ -17,4 +17,12 @@ public class ReturnOfInnerClass {
private Object four() {
return new B();
}
protected Object five() {
return new B();
}
Object six() {
return new B();
}
}
@@ -13,19 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.runners;
package com.siyeh.ig.cloneable;
import com.intellij.execution.console.ProcessBackedConsoleExecuteActionHandler;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
@SuppressWarnings({"ClassNameSameAsAncestorName", "UnusedDeclaration"})
@Deprecated
/**
* @deprecated Use {@link ProcessBackedConsoleExecuteActionHandler}
* to remove in IDEA 15
* @author Bas Leijdekkers
*/
public class ConsoleExecuteActionHandler extends ProcessBackedConsoleExecuteActionHandler {
public ConsoleExecuteActionHandler(ProcessHandler processHandler, boolean preserveMarkup) {
super(processHandler, preserveMarkup);
public class CloneInNonCloneableClassInspectionTest extends LightInspectionTestCase {
@Override
protected InspectionProfileEntry getInspection() {
return new CloneInNonCloneableClassInspection();
}
}
public void testCloneInNonCloneableClass() { doTest(); }
}
@@ -17,7 +17,6 @@ package com.siyeh.ig.memory;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import junit.framework.TestCase;
import org.jetbrains.annotations.Nullable;
/**
@@ -30,6 +29,8 @@ public class ReturnOfInnerClassInspectionTest extends LightInspectionTestCase {
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new ReturnOfInnerClassInspection();
final ReturnOfInnerClassInspection inspection = new ReturnOfInnerClassInspection();
inspection.ignoreNonPublic = true;
return inspection;
}
}
@@ -1,6 +1,6 @@
<html>
<body>
This intention replaces a <b><></b> (diamond) with the equivalent
This intention replaces a <b>&lt;&gt;</b> (diamond) with the equivalent
explicit type arguments.
<br><br>
</body>
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.ActionInfo;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitRevisionNumber;
import git4idea.GitUtil;
@@ -121,7 +122,7 @@ abstract class GitMergeAction extends GitRepositoryAction {
GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project);
VirtualFile root = repository.getRoot();
if (result.success()) {
root.refresh(false, true);
VfsUtil.markDirtyAndRefresh(false, true, false, root);
List<VcsException> exceptions = new ArrayList<VcsException>();
GitMergeUtil.showUpdates(this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE);
repositoryManager.updateRepository(root);
@@ -15,26 +15,63 @@
*/
package git4idea.push;
import com.intellij.dvcs.DvcsUtil;
import com.intellij.dvcs.push.PushSource;
import git4idea.GitLocalBranch;
import org.jetbrains.annotations.NotNull;
class GitPushSource implements PushSource {
abstract class GitPushSource implements PushSource {
@NotNull private final GitLocalBranch myBranch;
GitPushSource(@NotNull GitLocalBranch branch) {
myBranch = branch;
@NotNull
static GitPushSource create(@NotNull GitLocalBranch branch) {
return new OnBranch(branch);
}
@NotNull
@Override
public String getPresentation() {
return myBranch.getName();
static GitPushSource create(@NotNull String revision) {
return new DetachedHead(revision);
}
@NotNull
public GitLocalBranch getBranch() {
return myBranch;
abstract GitLocalBranch getBranch();
private static class OnBranch extends GitPushSource {
@NotNull private final GitLocalBranch myBranch;
private OnBranch(@NotNull GitLocalBranch branch) {
myBranch = branch;
}
@NotNull
@Override
public String getPresentation() {
return myBranch.getName();
}
@NotNull
@Override
GitLocalBranch getBranch() {
return myBranch;
}
}
private static class DetachedHead extends GitPushSource {
@NotNull private final String myRevision;
public DetachedHead(@NotNull String revision) {
myRevision = revision;
}
@NotNull
@Override
public String getPresentation() {
return DvcsUtil.getShortHash(myRevision);
}
@NotNull
@Override
GitLocalBranch getBranch() {
throw new IllegalStateException("Push is not allowed from detached HEAD");
}
}
}
@@ -81,6 +81,9 @@ public class GitPushSupport extends PushSupport<GitRepository, GitPushSource, Gi
@Nullable
@Override
public GitPushTarget getDefaultTarget(@NotNull GitRepository repository) {
if (repository.isFresh()) {
return null;
}
GitLocalBranch currentBranch = repository.getCurrentBranch();
if (currentBranch == null) {
return null;
@@ -123,7 +126,10 @@ public class GitPushSupport extends PushSupport<GitRepository, GitPushSource, Gi
@NotNull
@Override
public GitPushSource getSource(@NotNull GitRepository repository) {
return new GitPushSource(repository.getCurrentBranch()); // TODO assert: detached head => not possible to push
GitLocalBranch currentBranch = repository.getCurrentBranch();
return currentBranch != null
? GitPushSource.create(currentBranch)
: GitPushSource.create(ObjectUtils.assertNotNull(repository.getCurrentRevision())); // fresh repository is on branch
}
@NotNull
@@ -24,7 +24,6 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.awt.RelativePoint;
@@ -51,30 +50,40 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
private static final Comparator<GitRemoteBranch> REMOTE_BRANCH_COMPARATOR = new MyRemoteBranchComparator();
private static final String SEPARATOR = " : ";
private static final String NO_REMOTES = "No remotes";
private final GitRepository myRepository;
private final PushTargetTextField myTargetTextField;
private final JLabel myRemoteLabel;
@NotNull private final GitRepository myRepository;
@NotNull private final PushTargetTextField myTargetTextField;
@NotNull private final JLabel myRemoteLabel;
@NotNull private final ExtraEditControl myEditRemoteControl;
@Nullable private GitPushTarget myCurrentTarget;
@Nullable private String myError;
@Nullable private Runnable myFireOnChangeAction;
@NotNull private ExtraEditControl myEditRemoteControl;
public GitPushTargetPanel(@NotNull GitRepository repository, @Nullable GitPushTarget defaultTarget) {
myRepository = repository;
myCurrentTarget = defaultTarget;
String initialBranch;
String initialRemote;
String initialBranch = "";
String initialRemote = "";
if (defaultTarget == null) {
initialBranch = "";
initialRemote = NO_REMOTES;
if (repository.getCurrentBranch() == null) {
myError = "Detached HEAD";
}
else if (repository.getRemotes().isEmpty()) {
myError = "No remotes";
}
else if (repository.isFresh()) {
myError = "Empty repository";
}
else {
myError = "Can't push";
}
}
else {
initialBranch = getTextFieldText(defaultTarget);
initialRemote = getRemoteLabelText(defaultTarget.getBranch().getRemote().getName());
initialRemote = defaultTarget.getBranch().getRemote().getName();
}
myEditRemoteControl = new ExtraEditControl() {
@@ -89,7 +98,12 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
setLayout(new BorderLayout());
setOpaque(false);
add(myRemoteLabel, BorderLayout.WEST);
JPanel remoteAndSeparator = new JPanel(new BorderLayout());
remoteAndSeparator.setOpaque(false);
remoteAndSeparator.add(myRemoteLabel, BorderLayout.CENTER);
remoteAndSeparator.add(new JBLabel(SEPARATOR), BorderLayout.EAST);
add(remoteAndSeparator, BorderLayout.WEST);
add(myTargetTextField, BorderLayout.CENTER);
updateTextField();
}
@@ -107,7 +121,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
ListPopup popup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>(null, remotes) {
@Override
public PopupStep onChosen(String selectedValue, boolean finalChoice) {
myRemoteLabel.setText(getRemoteLabelText(selectedValue));
myRemoteLabel.setText(selectedValue);
if (myFireOnChangeAction != null) {
myFireOnChangeAction.run();
}
@@ -129,9 +143,8 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
@Override
public void render(@NotNull final ColoredTreeCellRenderer renderer) {
String targetName = myTargetTextField.getText();
if (StringUtil.isEmptyOrSpaces(targetName)) {
renderer.append(NO_REMOTES, SimpleTextAttributes.ERROR_ATTRIBUTES, this);
if (myError != null) {
renderer.append(myError, SimpleTextAttributes.ERROR_ATTRIBUTES);
}
else {
String currentRemote = myRemoteLabel.getText();
@@ -141,6 +154,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
else {
renderer.append(currentRemote, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
renderer.append(SEPARATOR, SimpleTextAttributes.REGULAR_ATTRIBUTES);
GitPushTarget target = getValue();
if (target.isNewBranchCreated()) {
@@ -161,10 +175,6 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
return (target != null ? target.getBranch().getNameForRemoteOperations() : "");
}
private static String getRemoteLabelText(@NotNull String selectedValue) {
return selectedValue + SEPARATOR;
}
@Override
public void fireOnCancel() {
myTargetTextField.setText(getTextFieldText(myCurrentTarget));
@@ -172,7 +182,10 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
@Override
public void fireOnChange() {
String remoteName = getEnteredRemote();
if (myError == null) {
return;
}
String remoteName = myRemoteLabel.getText();
String branchName = myTargetTextField.getText();
try {
myCurrentTarget = GitPushTarget.parse(myRepository, remoteName, branchName);
@@ -185,9 +198,11 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
@Nullable
@Override
public ValidationInfo verify() {
if (myError != null) {
return new ValidationInfo(myError, myTargetTextField);
}
try {
String remoteLabel = getEnteredRemote();
GitPushTarget.parse(myRepository, remoteLabel, myTargetTextField.getText());
GitPushTarget.parse(myRepository, myRemoteLabel.getText(), myTargetTextField.getText());
return null;
}
catch (ParseException e) {
@@ -195,17 +210,12 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
}
}
@SuppressWarnings("NullableProblems")
@Override
public void setFireOnChangeAction(@NotNull Runnable action) {
myFireOnChangeAction = action;
}
@Nullable
private String getEnteredRemote() {
String text = myRemoteLabel.getText();
return text.equals(NO_REMOTES) ? null : text.replace(SEPARATOR, "");
}
@NotNull
public static List<String> getTargetNames(@NotNull GitRepository repository) {
List<GitRemoteBranch> remoteBranches = ContainerUtil.sorted(repository.getBranches().getRemoteBranches(), REMOTE_BRANCH_COMPARATOR);
@@ -219,7 +229,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
private static class MyRemoteBranchComparator implements Comparator<GitRemoteBranch> {
@Override
public int compare(GitRemoteBranch o1, GitRemoteBranch o2) {
public int compare(@NotNull GitRemoteBranch o1, @NotNull GitRemoteBranch o2) {
String remoteName1 = o1.getRemote().getName();
String remoteName2 = o2.getRemote().getName();
int remoteComparison = remoteName1.compareTo(remoteName2);
@@ -138,7 +138,7 @@ abstract class GitPushOperationBaseTest extends GitPlatformTest {
else {
newBranch = false;
}
return new PushSpec<GitPushSource, GitPushTarget>(new GitPushSource(source), new GitPushTarget(target, newBranch));
return new PushSpec<GitPushSource, GitPushTarget>(GitPushSource.create(source), new GitPushTarget(target, newBranch));
}
@NotNull
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.github.ui.GithubSettingsPanel">
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="5" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="6" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="646" height="400"/>
@@ -13,7 +13,7 @@
<children>
<component id="28ddd" class="javax.swing.JTextPane" binding="mySignupTextField">
<constraints>
<grid row="2" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false">
<grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="10"/>
</grid>
</constraints>
@@ -28,7 +28,7 @@
</component>
<vspacer id="6ace">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="45bab" class="com.intellij.ui.components.JBLabel">
@@ -167,13 +167,13 @@
<grid id="d384a" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="4" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<html.disable class="java.lang.Boolean" value="false"/>
</clientProperties>
<border type="etched" title="Other Settings:"/>
<border type="none"/>
<children>
<component id="ae995" class="javax.swing.JLabel">
<constraints>
@@ -204,6 +204,15 @@
</component>
</children>
</grid>
<vspacer id="2a9d8">
<constraints>
<grid row="3" column="0" row-span="1" col-span="5" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="-1" height="15"/>
<preferred-size width="-1" height="15"/>
<maximum-size width="-1" height="15"/>
</grid>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -254,8 +254,11 @@ public class ClassWriter {
if (hasContent) {
buffer.appendLineSeparator();
startLine++;
}
classToJava(inner, buffer, indent + 1, tracer);
BytecodeMappingTracer class_tracer = new BytecodeMappingTracer(startLine);
classToJava(inner, buffer, indent + 1, class_tracer);
startLine = buffer.countLines();
hasContent = true;
}
@@ -840,7 +843,7 @@ public class ClassWriter {
// save total lines
// TODO: optimize
tracer.setCurrentSourceLine(buffer.countLines(start_index_method));
//tracer.setCurrentSourceLine(buffer.countLines(start_index_method));
return !hideMethod;
}
@@ -280,6 +280,7 @@ public class ClassesProcessor {
}
//buffer.append(lineSeparator);
total_offset_lines = buffer.countLines();
buffer.append(classBuffer);
if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
@@ -97,7 +97,7 @@ public class BytecodeSourceMapper {
buffer.append("Lines mapping:").appendLineSeparator();
Map<Integer, Integer> sorted = new TreeMap<Integer, Integer>(linesMapping);
for (Entry<Integer, Integer> entry : sorted.entrySet()) {
buffer.append(entry.getKey()).append(" <-> ").append(entry.getValue()).appendLineSeparator();
buffer.append(entry.getKey()).append(" <-> ").append(entry.getValue()+ offset_total + 1).appendLineSeparator();
}
}
@@ -187,7 +187,6 @@ public class CatchStatement extends Statement {
tracer.incrementCurrentSourceLine();
buf.append(ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true, tracer)).append(indstr)
.append("}");
tracer.incrementCurrentSourceLine();
}
buf.append(new_line_separator);
@@ -8,6 +8,7 @@ public class TestClassSimpleBytecodeMapping {
System.out.println("Runnable");
}
});
this.test2("1");
if(Math.random() > 0.0D) {
System.out.println("0");
return 0;
@@ -17,9 +18,30 @@ public class TestClassSimpleBytecodeMapping {
}
}
public void test2(String var1) {
try {
Integer.parseInt(var1);
} catch (Exception var3) {
System.out.println(var3);
}
}
void run(Runnable var1) {
var1.run();
}
public class InnerClass2 {
public void print() {
System.out.println("Inner2");
}
}
public class InnerClass {
public void print() {
System.out.println("Inner");
}
}
}
class 'pkg/TestClassSimpleBytecodeMapping$1' {
@@ -36,34 +58,60 @@ class 'pkg/TestClassSimpleBytecodeMapping' {
3 4
5 4
11 5
14 10
15 10
17 10
18 10
19 10
1c 11
1a 11
1d 11
1e 11
1f 11
21 11
24 12
22 12
25 12
26 14
29 14
2b 14
2e 15
27 12
2a 13
2b 13
2c 15
2f 15
31 15
34 16
35 16
}
method 'test2 (Ljava/lang/String;)V' {
1 22
}
method 'run (Ljava/lang/Runnable;)V' {
1 20
1 30
}
}
class 'pkg/TestClassSimpleBytecodeMapping$InnerClass2' {
method 'print ()V' {
0 35
3 35
5 35
}
}
class 'pkg/TestClassSimpleBytecodeMapping$InnerClass' {
method 'print ()V' {
0 41
3 41
5 41
}
}
Lines mapping:
12 <-> 2
14 <-> 3
17 <-> 5
21 <-> 8
22 <-> 9
23 <-> 10
25 <-> 12
26 <-> 13
31 <-> 18
12 <-> 5
14 <-> 6
17 <-> 8
21 <-> 11
23 <-> 12
24 <-> 13
25 <-> 14
27 <-> 16
28 <-> 17
34 <-> 23
42 <-> 42
47 <-> 31
52 <-> 36
@@ -18,6 +18,8 @@ public class TestClassSimpleBytecodeMapping {
}
});
test2("1");
if(Math.random() > 0) {
System.out.println("0");
return 0;
@@ -27,7 +29,27 @@ public class TestClassSimpleBytecodeMapping {
}
}
public void test2(String a) {
try {
Integer.parseInt(a);
} catch (Exception e) {
System.out.println(e);
}
}
public class InnerClass {
public void print() {
System.out.println("Inner");
}
}
void run(Runnable r) {
r.run();
}
public class InnerClass2 {
public void print() {
System.out.println("Inner2");
}
}
}
@@ -5593,9 +5593,9 @@ action.MarkAsOriginalTypeAction.text=Mark as
action.Console.Execute.text=Execute Current Statement
action.Console.Execute.description=Execute current statement in console
action.Console.History.Previous.text=Previous
action.Console.History.Previous.text=Previous history entry
action.Console.History.Previous.description=Previous console history entry
action.Console.History.Next.text=Next
action.Console.History.Next.text=Next history entry
action.Console.History.Next.description=Next console history entry
action.Console.History.Browse.text=Browse History
action.Console.History.Browse.description=Browse console history
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myComponent" layout-manager="GridLayoutManager" row-count="7" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="1135" height="631"/>
<xy x="20" y="20" width="1135" height="646"/>
</constraints>
<properties/>
<clientProperties>
@@ -240,7 +240,7 @@
</component>
</children>
</grid>
<grid id="84b94" layout-manager="GridLayoutManager" row-count="8" column-count="31" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="84b94" layout-manager="GridLayoutManager" row-count="10" column-count="31" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<tabbedpane title="Network"/>
@@ -250,7 +250,7 @@
<children>
<vspacer id="95e5d">
<constraints>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="1283d" class="javax.swing.JCheckBox" binding="myUseCommonProxy">
@@ -264,7 +264,7 @@
<grid id="96256" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="7" column="0" row-span="1" col-span="31" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="9" column="0" row-span="1" col-span="31" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -304,19 +304,20 @@
<text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="use.idea.proxy.as.default.label.text"/>
</properties>
</component>
<grid id="9e56c" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="6d452" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="9c08f" class="javax.swing.JLabel">
<component id="9c08f" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<anchor value="234"/>
<text value="HTTP timeout:"/>
</properties>
</component>
@@ -328,30 +329,6 @@
</constraints>
<properties/>
</component>
<component id="234" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="SSH connection timeout:"/>
</properties>
</component>
<component id="21604" class="javax.swing.JSpinner" binding="mySSHConnectionTimeout" custom-create="true">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
<preferred-size width="70" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="6949c" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="seconds"/>
</properties>
</component>
<component id="c9190" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
@@ -360,102 +337,159 @@
<text value="seconds"/>
</properties>
</component>
<component id="a770c" class="javax.swing.JLabel">
</children>
</grid>
<grid id="6ae1d" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="234" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="seconds"/>
<text value="SSH connection timeout:"/>
</properties>
</component>
<component id="8e59f" class="javax.swing.JSpinner" binding="mySSHReadTimeout" custom-create="true">
<component id="21604" class="javax.swing.JSpinner" binding="mySSHConnectionTimeout" custom-create="true">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
<preferred-size width="70" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="44801" class="javax.swing.JLabel">
<component id="6949c" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="SSH read timeout:"/>
<text value="seconds"/>
</properties>
</component>
</children>
</grid>
<hspacer id="29b97">
<constraints>
<grid row="3" column="3" row-span="1" col-span="28" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<grid id="4756d" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="85015" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<grid id="4b641" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<grid id="fdb89" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="SSL protocols"/>
<children>
<component id="a97cb" class="com.intellij.ui.components.JBRadioButton" binding="mySSLv3RadioButton" default-binding="true">
<component id="44801" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="SSLv3"/>
<anchor value="234"/>
<text value="SSH read timeout:"/>
</properties>
</component>
<component id="48af1" class="com.intellij.ui.components.JBRadioButton" binding="myTLSv1RadioButton" default-binding="true">
<component id="8e59f" class="javax.swing.JSpinner" binding="mySSHReadTimeout" custom-create="true">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
<preferred-size width="70" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="a770c" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="TLSv1"/>
<text value="seconds"/>
</properties>
</component>
<component id="5c1ce" class="com.intellij.ui.components.JBRadioButton" binding="myAllRadioButton" default-binding="true">
</children>
</grid>
<grid id="2a91c" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="1528f" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="All"/>
<anchor value="234"/>
<text value="SSL protocols:"/>
<verticalAlignment value="0"/>
</properties>
</component>
<component id="98a95" class="javax.swing.JLabel" binding="mySSLExplicitly">
<grid id="fdb89" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="a97cb" class="com.intellij.ui.components.JBRadioButton" binding="mySSLv3RadioButton" default-binding="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="SSLv3"/>
</properties>
</component>
<component id="48af1" class="com.intellij.ui.components.JBRadioButton" binding="myTLSv1RadioButton" default-binding="true">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="TLSv1"/>
</properties>
</component>
<component id="5c1ce" class="com.intellij.ui.components.JBRadioButton" binding="myAllRadioButton" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="All"/>
</properties>
</component>
</children>
</grid>
<component id="98a95" class="com.intellij.ui.components.JBLabel" binding="mySSLExplicitly">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
</constraints>
<properties>
<componentStyle value="SMALL"/>
<fontColor value="BRIGHTER"/>
<text value=""/>
</properties>
</component>
</children>
</grid>
<hspacer id="c45eb">
<vspacer id="e6874">
<constraints>
<grid row="5" column="1" row-span="1" col-span="12" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="-1" height="15"/>
<preferred-size width="-1" height="15"/>
<maximum-size width="-1" height="15"/>
</grid>
</constraints>
</hspacer>
</vspacer>
<vspacer id="2b945">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="-1" height="15"/>
<preferred-size width="-1" height="15"/>
<maximum-size width="-1" height="15"/>
</grid>
</constraints>
</vspacer>
</children>
</grid>
<grid id="763be" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
@@ -125,10 +125,12 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
patternText.append("\n");
}
int patternLength = patternText.length();
if (patternText.charAt(patternLength - 1) == '\n') {
patternText.delete(patternLength - 1, patternLength);
if (patternLength != 0) {
if (patternText.charAt(patternLength - 1) == '\n') {
patternText.delete(patternLength - 1, patternLength);
}
document.setText(patternText);
}
document.setText(patternText);
}
catch (FileNotFoundException e) {
LOG.error(e);
@@ -0,0 +1,59 @@
package com.intellij.updater;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public abstract class BaseDeleteAction extends PatchAction {
public BaseDeleteAction(String path, long checksum) {
super(path, checksum);
}
public BaseDeleteAction(DataInputStream in) throws IOException {
super(in);
}
@Override
public void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
// do nothing
}
@Override
protected ValidationResult doValidate(File toFile) throws IOException {
ValidationResult result = doValidateAccess(toFile, ValidationResult.Action.DELETE);
if (result != null) return result;
if (toFile.exists() && isModified(toFile)) {
return new ValidationResult(ValidationResult.Kind.CONFLICT,
myPath,
ValidationResult.Action.DELETE,
"Modified",
ValidationResult.Option.DELETE,
ValidationResult.Option.KEEP);
}
return null;
}
@Override
protected boolean shouldApplyOn(File toFile) {
return toFile.exists();
}
@Override
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
Utils.delete(toFile);
}
protected void doBackup(File toFile, File backupFile) throws IOException {
Utils.copy(toFile, backupFile);
}
protected void doRevert(File toFile, File backupFile) throws IOException {
if (!toFile.exists() || toFile.isDirectory() || isModified(toFile)) {
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
Utils.copy(backupFile, toFile);
}
}
}
@@ -35,13 +35,7 @@ public abstract class BaseUpdateAction extends PatchAction {
protected void replaceUpdated(File from, File dest) throws IOException {
// on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
if (!dest.delete()) {
if (Utils.isWindows()) {
throw new RetryException("Cannot delete file " + dest);
} else {
throw new IOException("Cannot delete file " + dest);
}
}
if (!dest.delete()) throw new IOException("Cannot delete file " + dest);
Utils.copy(from, dest);
}
@@ -42,6 +42,11 @@ public class CreateAction extends PatchAction {
return null;
}
@Override
protected boolean isModified(File toFile) throws IOException {
return false;
}
@Override
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
prepareToWriteFile(toFile);
@@ -59,15 +64,7 @@ public class CreateAction extends PatchAction {
private static void prepareToWriteFile(File file) throws IOException {
if (file.exists()) {
try {
Utils.delete(file);
} catch (IOException e) {
if (Utils.isWindows() && file.exists()) {
throw new RetryException(e);
} else {
throw e;
}
}
Utils.delete(file);
return;
}
@@ -3,10 +3,8 @@ package com.intellij.updater;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class DeleteAction extends PatchAction {
public class DeleteAction extends BaseDeleteAction {
public DeleteAction(String path, long checksum) {
super(path, checksum);
}
@@ -16,54 +14,7 @@ public class DeleteAction extends PatchAction {
}
@Override
public void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
// do nothing
}
@Override
protected ValidationResult doValidate(File toFile) throws IOException {
ValidationResult result = doValidateAccess(toFile, ValidationResult.Action.DELETE);
if (result != null) return result;
if (toFile.exists() && isModified(toFile)) {
return new ValidationResult(ValidationResult.Kind.CONFLICT,
myPath,
ValidationResult.Action.DELETE,
"Modified",
ValidationResult.Option.DELETE,
ValidationResult.Option.KEEP);
}
return null;
}
@Override
protected boolean shouldApplyOn(File toFile) {
return toFile.exists();
}
@Override
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
try {
Utils.delete(toFile);
} catch (IOException e) {
if (Utils.isWindows() && toFile.exists()) {
throw new RetryException(e);
} else {
throw e;
}
}
}
@Override
protected void doBackup(File toFile, File backupFile) throws IOException {
Utils.copy(toFile, backupFile);
}
@Override
protected void doRevert(File toFile, File backupFile) throws IOException {
if (!toFile.exists() || isModified(toFile)) {
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
Utils.copy(backupFile, toFile);
}
protected boolean isModified(File toFile) throws IOException {
return myChecksum != Digester.digestRegularFile(toFile);
}
}
@@ -0,0 +1,20 @@
package com.intellij.updater;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
public class DeleteZipAction extends BaseDeleteAction {
public DeleteZipAction(String path, long checksum) {
super(path, checksum);
}
public DeleteZipAction(DataInputStream in) throws IOException {
super(in);
}
@Override
protected boolean isModified(File toFile) throws IOException {
return myChecksum != Digester.digestFile(toFile);
}
}
@@ -22,15 +22,14 @@ public class Digester {
}
public static long digestFile(File file) throws IOException {
if (Utils.isZipFile(file.getName())) {
if (!Runner.ZIP_AS_BINARY && Utils.isZipFile(file.getName())) {
ZipFile zipFile;
try {
zipFile = new ZipFile(file);
}
catch (IOException e) {
// If this isn't a zip file, this isn't really an error, merely an info.
Runner.infoStackTrace("Can't open file as zip file: " + file.getPath() + "\n", e);
return doDigestRegularFile(file);
Runner.printStackTrace(e);
return digestRegularFile(file);
}
try {
@@ -40,10 +39,10 @@ public class Digester {
zipFile.close();
}
}
return doDigestRegularFile(file);
return digestRegularFile(file);
}
private static long doDigestRegularFile(File file) throws IOException {
public static long digestRegularFile(File file) throws IOException {
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
return digestStream(in);
@@ -0,0 +1,113 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.updater;
import com.sun.jna.Pointer;
import com.sun.jna.StringArray;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
/**
* A utility class to find processes that hold a lock to a file. This relies on a Windows API called
* RestartManager {@see http://msdn.microsoft.com/en-us/library/windows/desktop/cc948910(v=vs.85).aspx}
*
* This class uses the RestartManager and the Kernel32 APIs, and it tries to initialize them the first
* time it is run. If the RestartManager DLL is not found, it being because we are running on XP or
* because we are not running on Windows, then the class is flagged as failed and no further attempts
* will be made to load the DLL.
*/
public class NativeFileManager {
private static final int MAX_PROCESSES = 10;
private static boolean ourFailed = false;
public static class Process {
public final int pid;
public final String name;
public Process(int pid, String name) {
this.pid = pid;
this.name = name;
}
public boolean terminate() {
Kernel32.HANDLE process = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_TERMINATE | WinNT.SYNCHRONIZE, false, pid);
if (process.getPointer() == null) {
Runner.logger.warn("Unable to find process " + name + "(" + pid + ")");
return false;
} else {
Kernel32.INSTANCE.TerminateProcess(process, 1);
int wait = Kernel32.INSTANCE.WaitForSingleObject(process, 1000);
if (wait != WinBase.WAIT_OBJECT_0) {
Runner.logger.warn("Timed out while waiting for process " + name + "(" + pid + ") to end");
return false;
}
Kernel32.INSTANCE.CloseHandle(process);
return true;
}
}
}
public static List<Process> getProcessesUsing(File file) {
List<Process> processes = new LinkedList<Process>();
// If the DLL was not present (XP or other OS), do not try to find it again.
if (ourFailed) {
return processes;
}
try {
IntByReference session = new IntByReference();
char[] sessionKey = new char[Win32RestartManager.CCH_RM_SESSION_KEY + 1];
int error = Win32RestartManager.INSTANCE.RmStartSession(session, 0, sessionKey);
if (error != 0) {
Runner.logger.warn("Unable to start restart manager session");
return processes;
}
StringArray resources = new StringArray(new WString[]{new WString(file.toString())});
error = Win32RestartManager.INSTANCE.RmRegisterResources(session.getValue(), 1, resources, 0, Pointer.NULL, 0, null);
if (error != 0) {
Runner.logger.warn("Unable to register restart manager resource " + file.getAbsolutePath());
return processes;
}
IntByReference procInfoNeeded = new IntByReference();
Win32RestartManager.RmProcessInfo info = new Win32RestartManager.RmProcessInfo();
Win32RestartManager.RmProcessInfo[] infos = (Win32RestartManager.RmProcessInfo[])info.toArray(MAX_PROCESSES);
IntByReference procInfo = new IntByReference(infos.length);
error = Win32RestartManager.INSTANCE.RmGetList(session.getValue(), procInfoNeeded, procInfo, info, new LongByReference());
if (error != 0) {
Runner.logger.warn("Unable to get the list of processes using " + file.getAbsolutePath());
return processes;
}
for (int i = 0; i < procInfo.getValue(); i++) {
processes.add(new Process(infos[i].Process.dwProcessId, new String(infos[i].strAppName).trim()));
}
Win32RestartManager.INSTANCE.RmEndSession(session.getValue());
} catch (Throwable t) {
// Best effort approach, if no DLL is found ignore.
ourFailed = true;
}
return processes;
}
}
+14 -2
View File
@@ -11,6 +11,7 @@ public class Patch {
private static final int UPDATE_ACTION_KEY = 2;
private static final int UPDATE_ZIP_ACTION_KEY = 3;
private static final int DELETE_ACTION_KEY = 4;
private static final int DELETE_ZIP_ACTION_KEY = 5;
public Patch(File olderDir,
File newerDir,
@@ -45,7 +46,12 @@ public class Patch {
// 'delete' actions before 'create' actions to prevent newly created files to be deleted if the names differ only on case.
for (Map.Entry<String, Long> each : diff.filesToDelete.entrySet()) {
tempActions.add(new DeleteAction(each.getKey(), each.getValue()));
if (!Runner.ZIP_AS_BINARY && Utils.isZipFile(each.getKey())) {
tempActions.add(new DeleteZipAction(each.getKey(), each.getValue()));
} else
{
tempActions.add(new DeleteAction(each.getKey(), each.getValue()));
}
}
for (String each : diff.filesToCreate) {
@@ -53,7 +59,7 @@ public class Patch {
}
for (Map.Entry<String, Long> each : diff.filesToUpdate.entrySet()) {
if (Utils.isZipFile(each.getKey())) {
if (!Runner.ZIP_AS_BINARY && Utils.isZipFile(each.getKey())) {
tempActions.add(new UpdateZipAction(each.getKey(), each.getValue()));
}
else {
@@ -98,6 +104,9 @@ public class Patch {
else if (clazz == UpdateZipAction.class) {
key = UPDATE_ZIP_ACTION_KEY;
}
else if (clazz == DeleteZipAction.class) {
key = DELETE_ZIP_ACTION_KEY;
}
else if (clazz == DeleteAction.class) {
key = DELETE_ACTION_KEY;
}
@@ -135,6 +144,9 @@ public class Patch {
case DELETE_ACTION_KEY:
a = new DeleteAction(in);
break;
case DELETE_ZIP_ACTION_KEY:
a = new DeleteZipAction(in);
break;
default:
throw new RuntimeException("Unknown action type " + key);
}
@@ -4,6 +4,8 @@ import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
@@ -60,9 +62,15 @@ public abstract class PatchAction {
protected abstract void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException;
public boolean shouldApply(File toDir, Map<String, ValidationResult.Option> options) {
File file = getFile(toDir);
ValidationResult.Option option = options.get(myPath);
if (option == ValidationResult.Option.KEEP || option == ValidationResult.Option.IGNORE) return false;
return shouldApplyOn(getFile(toDir));
if (option == ValidationResult.Option.KILL_PROCESS) {
for (NativeFileManager.Process process : NativeFileManager.getProcessesUsing(file)) {
process.terminate();
}
}
return shouldApplyOn(file);
}
protected boolean shouldApplyOn(File toFile) {
@@ -78,6 +86,10 @@ public abstract class PatchAction {
protected ValidationResult doValidateAccess(File toFile, ValidationResult.Action action) {
if (!toFile.exists()) return null;
if (toFile.isDirectory()) return null;
ValidationResult result = validateProcessLock(toFile, action);
if (result != null) {
return result;
}
if (toFile.canRead() && toFile.canWrite() && isWritable(toFile)) return null;
return new ValidationResult(ValidationResult.Kind.ERROR,
myPath,
@@ -111,6 +123,23 @@ public abstract class PatchAction {
}
}
private ValidationResult validateProcessLock(File toFile, ValidationResult.Action action) {
List<NativeFileManager.Process> processes = NativeFileManager.getProcessesUsing(toFile);
if (processes.size() > 0) {
Iterator<NativeFileManager.Process> it = processes.iterator();
String message = "Locked by: " + it.next().name;
while (it.hasNext()) {
message += ", " + it.next().name;
}
return new ValidationResult(ValidationResult.Kind.ERROR,
myPath,
action,
message,
ValidationResult.Option.KILL_PROCESS);
}
return null;
}
protected ValidationResult doValidateNotChanged(File toFile, ValidationResult.Kind kind, ValidationResult.Action action)
throws IOException {
if (toFile.exists()) {
@@ -132,9 +161,7 @@ public abstract class PatchAction {
return null;
}
protected boolean isModified(File toFile) throws IOException {
return myChecksum != Digester.digestFile(toFile);
}
abstract protected boolean isModified(File toFile) throws IOException;
public void apply(ZipFile patchFile, File toDir) throws IOException {
doApply(patchFile, getFile(toDir));
@@ -1,39 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.updater;
import java.io.IOException;
/**
* Exception thrown when an IOException arises when performing a patch
* action and it's likely that retrying will be successful.
*/
public class RetryException extends IOException {
public RetryException() {
}
public RetryException(String message) {
super(message);
}
public RetryException(String message, Throwable cause) {
super(message, cause);
}
public RetryException(Throwable cause) {
super(cause);
}
}
+32 -71
View File
@@ -18,6 +18,13 @@ import java.util.zip.ZipInputStream;
public class Runner {
public static Logger logger = null;
/**
* Treats zip files as regular binary files. When false, zip/jar files are unzipped and diffed file by file.
* When true, the entire zip file is diffed as a single file. Set to true if preserving the timestamps of
* the files inside the zip is important. This variable can change via a command line option.
*/
public static boolean ZIP_AS_BINARY = false;
private static final String PATCH_FILE_NAME = "patch-file.zip";
private static final String PATCH_PROPERTIES_ENTRY = "patch.properties";
private static final String OLD_BUILD_DESCRIPTION = "old.build.description";
@@ -32,28 +39,19 @@ public class Runner {
String patchFile = args[5];
initLogger();
ZIP_AS_BINARY = Arrays.asList(args).contains("--zip_as_binary");
List<String> ignoredFiles = extractFiles(args, "ignored");
List<String> criticalFiles = extractFiles(args, "critical");
List<String> optionalFiles = extractFiles(args, "optional");
create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
}
else if (args.length >= 2 && "install".equals(args[0])) {
// install [--exit0] <destination_folder>
int nextArg = 1;
// Default install exit code is SwingUpdaterUI.RESULT_REQUIRES_RESTART (42) unless overridden to be 0.
// This is used by testUI/build.gradle as gradle expects a javaexec to exit with code 0.
boolean useExitCode0 = false;
if (args[nextArg].equals("--exit0")) {
useExitCode0 = true;
nextArg++;
}
String destFolder = args[nextArg++];
String destFolder = args[1];
initLogger();
logger.info("destFolder: " + destFolder);
install(useExitCode0, destFolder);
install(destFolder);
}
else {
printUsage();
@@ -104,10 +102,6 @@ public class Runner {
}
}
public static void infoStackTrace(String msg, Throwable e){
logger.info(msg, e);
}
public static void printStackTrace(Throwable e){
logger.error(e.getMessage(), e);
}
@@ -130,8 +124,8 @@ public class Runner {
private static void printUsage() {
System.err.println("Usage:\n" +
"create <old_version_description> <new_version_description> <old_version_folder> <new_version_folder>" +
" <patch_file_name> <log_directory> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
"install [--exit0] <destination_folder> [log_directory]\n");
" <patch_file_name> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
"install <destination_folder>\n");
}
private static void create(String oldBuildDesc,
@@ -142,31 +136,9 @@ public class Runner {
List<String> ignoredFiles,
List<String> criticalFiles,
List<String> optionalFiles) throws IOException, OperationCancelledException {
File tempPatchFile = Utils.createTempFile();
createImpl(oldBuildDesc,
newBuildDesc,
oldFolder,
newFolder,
patchFile,
tempPatchFile,
ignoredFiles,
criticalFiles,
optionalFiles,
new ConsoleUpdaterUI(), resolveJarFile());
}
static void createImpl(String oldBuildDesc,
String newBuildDesc,
String oldFolder,
String newFolder,
String outPatchJar,
File tempPatchFile,
List<String> ignoredFiles,
List<String> criticalFiles,
List<String> optionalFiles,
UpdaterUI ui,
File resolvedJar) throws IOException, OperationCancelledException {
UpdaterUI ui = new ConsoleUpdaterUI();
try {
File tempPatchFile = Utils.createTempFile();
PatchFileCreator.create(new File(oldFolder),
new File(newFolder),
tempPatchFile,
@@ -175,13 +147,13 @@ public class Runner {
optionalFiles,
ui);
logger.info("Packing JAR file: " + outPatchJar );
ui.startProcess("Packing JAR file '" + outPatchJar + "'...");
logger.info("Packing JAR file: " + patchFile );
ui.startProcess("Packing JAR file '" + patchFile + "'...");
FileOutputStream fileOut = new FileOutputStream(outPatchJar);
FileOutputStream fileOut = new FileOutputStream(patchFile);
try {
ZipOutputWrapper out = new ZipOutputWrapper(fileOut);
ZipInputStream in = new ZipInputStream(new FileInputStream(resolvedJar));
ZipInputStream in = new ZipInputStream(new FileInputStream(resolveJarFile()));
try {
ZipEntry e;
while ((e = in.getNextEntry()) != null) {
@@ -223,14 +195,16 @@ public class Runner {
Utils.cleanup();
}
private static void install(final boolean useExitCode0, final String destFolder) throws Exception {
private static void install(final String destFolder) throws Exception {
InputStream in = Runner.class.getResourceAsStream("/" + PATCH_PROPERTIES_ENTRY);
Properties props = new Properties();
try {
props.load(in);
}
finally {
in.close();
if (in != null) {
try {
props.load(in);
}
finally {
in.close();
}
}
// todo[r.sh] to delete in IDEA 14 (after a full circle of platform updates)
@@ -250,9 +224,7 @@ public class Runner {
new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
props.getProperty(NEW_BUILD_DESCRIPTION),
useExitCode0 ? 0 : SwingUpdaterUI.RESULT_REQUIRES_RESTART,
new SwingUpdaterUI.InstallOperation() {
@Override
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
logger.info("installing patch to the " + destFolder);
return doInstall(ui, destFolder);
@@ -260,26 +232,11 @@ public class Runner {
});
}
interface IJarResolver {
File resolveJar() throws IOException;
}
private static boolean doInstall(UpdaterUI ui, String destFolder) throws OperationCancelledException {
return doInstallImpl(ui, destFolder, new IJarResolver() {
@Override
public File resolveJar() throws IOException {
return resolveJarFile();
}
});
}
static boolean doInstallImpl(UpdaterUI ui,
String destFolder,
IJarResolver jarResolver) throws OperationCancelledException {
try {
try {
File patchFile = Utils.createTempFile();
ZipFile jarFile = new ZipFile(jarResolver.resolveJar());
ZipFile jarFile = new ZipFile(resolveJarFile());
logger.info("Extracting patch file...");
ui.startProcess("Extracting patch file...");
@@ -325,6 +282,10 @@ public class Runner {
}
private static File resolveJarFile() throws IOException {
String jar = System.getProperty("JAR_FILE");
if (jar != null) {
return new File(jar);
}
URL url = Runner.class.getResource("");
if (url == null) throw new IOException("Cannot resolve JAR file path");
if (!"jar".equals(url.getProtocol())) throw new IOException("Patch file is not a JAR file");
@@ -10,7 +10,6 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
@@ -20,7 +19,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
public class SwingUpdaterUI implements UpdaterUI {
static final int RESULT_REQUIRES_RESTART = 42;
private static final int RESULT_REQUIRES_RESTART = 42;
private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
@@ -33,7 +32,6 @@ public class SwingUpdaterUI implements UpdaterUI {
private static final String PROCEED_BUTTON_TITLE = "Proceed";
private final int mySuccessExitCode;
private final InstallOperation myOperation;
private final JLabel myProcessTitle;
@@ -42,30 +40,16 @@ public class SwingUpdaterUI implements UpdaterUI {
private final JTextArea myConsole;
private final JPanel myConsolePane;
private final JButton myRetryButton;
private final JButton myCancelButton;
private final ConcurrentLinkedQueue<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
private final AtomicBoolean isCancelled = new AtomicBoolean(false);
private final AtomicBoolean isRunning = new AtomicBoolean(false);
private final AtomicBoolean hasError = new AtomicBoolean(false);
private final AtomicBoolean hasRetry = new AtomicBoolean(false);
private final JFrame myFrame;
private boolean myApplied;
/**
* Displays the updater UI and asynchronously runs the operation list.
*
* @param oldBuildDesc The old build description, for display purposes.
* @param newBuildDesc The new build description, for display purposes.
* @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
* @param operation The install operations to perform.
*/
public SwingUpdaterUI(String oldBuildDesc,
String newBuildDesc,
int successExitCode,
InstallOperation operation) {
mySuccessExitCode = successExitCode;
public SwingUpdaterUI(String oldBuildDesc, String newBuildDesc, InstallOperation operation) {
myOperation = operation;
myProcessTitle = new JLabel(" ");
@@ -74,10 +58,6 @@ public class SwingUpdaterUI implements UpdaterUI {
myCancelButton = new JButton(CANCEL_BUTTON_TITLE);
myRetryButton = new JButton("Retry");
myRetryButton.setEnabled(false);
myRetryButton.setVisible(false);
myConsole = new JTextArea();
myConsole.setLineWrap(true);
myConsole.setWrapStyleWord(true);
@@ -90,19 +70,11 @@ public class SwingUpdaterUI implements UpdaterUI {
myConsolePane.setVisible(false);
myCancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doCancel();
}
});
myRetryButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doRetry();
}
});
myFrame = new JFrame();
myFrame.setTitle(TITLE);
@@ -132,7 +104,6 @@ public class SwingUpdaterUI implements UpdaterUI {
buttonsPanel.setBorder(BUTTONS_BORDER);
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
buttonsPanel.add(Box.createHorizontalGlue());
buttonsPanel.add(myRetryButton);
buttonsPanel.add(myCancelButton);
myProcessTitle.setText("<html>Updating " + oldBuildDesc + " to " + newBuildDesc + "...");
@@ -158,7 +129,6 @@ public class SwingUpdaterUI implements UpdaterUI {
private void startRequestDispatching() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
@@ -176,7 +146,6 @@ public class SwingUpdaterUI implements UpdaterUI {
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (UpdateRequest each : pendingRequests) {
each.perform();
@@ -203,28 +172,10 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
private void doRetry() {
hasError.set(false);
hasRetry.set(false);
isCancelled.set(false);
myQueue.add(new UpdateRequest() {
@Override
public void perform() {
myConsole.setText("");
myConsolePane.setVisible(false);
myConsolePane.setPreferredSize(new Dimension(10, 200));
myRetryButton.setEnabled(false);
myCancelButton.setEnabled(true);
}
});
doPerform();
}
private void doPerform() {
isRunning.set(true);
new Thread(new Runnable() {
@Override
public void run() {
try {
myApplied = myOperation.execute(SwingUpdaterUI.this);
@@ -239,10 +190,6 @@ public class SwingUpdaterUI implements UpdaterUI {
finally {
isRunning.set(false);
if (hasRetry.get()) {
myRetryButton.setVisible(true);
myRetryButton.setEnabled(true);
}
if (hasError.get()) {
startProcess("Failed to apply patch");
setProgress(100);
@@ -257,17 +204,15 @@ public class SwingUpdaterUI implements UpdaterUI {
}
private void exit() {
System.exit(myApplied ? mySuccessExitCode : 0);
System.exit(myApplied ? RESULT_REQUIRES_RESTART : 0);
}
@Override
public Map<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
if (validationResults.isEmpty()) return Collections.emptyMap();
final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
final JDialog dialog = new JDialog(myFrame, TITLE, true);
dialog.setLayout(new BorderLayout());
@@ -279,7 +224,6 @@ public class SwingUpdaterUI implements UpdaterUI {
buttonsPanel.add(Box.createHorizontalGlue());
JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
proceedButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
@@ -287,7 +231,6 @@ public class SwingUpdaterUI implements UpdaterUI {
JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
isCancelled.set(true);
myCancelButton.setEnabled(false);
@@ -344,10 +287,8 @@ public class SwingUpdaterUI implements UpdaterUI {
return result;
}
@Override
public void startProcess(final String title) {
myQueue.add(new UpdateRequest() {
@Override
public void perform() {
myProcessStatus.setText(title);
myProcessProgress.setIndeterminate(false);
@@ -356,10 +297,8 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
@Override
public void setProgress(final int percentage) {
myQueue.add(new UpdateRequest() {
@Override
public void perform() {
myProcessProgress.setIndeterminate(false);
myProcessProgress.setValue(percentage);
@@ -367,43 +306,21 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
@Override
public void setProgressIndeterminate() {
myQueue.add(new UpdateRequest() {
@Override
public void perform() {
myProcessProgress.setIndeterminate(true);
}
});
}
@Override
public void setStatus(final String status) {
}
@Override
public void showError(final Throwable e) {
hasError.set(true);
StringWriter w = new StringWriter();
if (e instanceof RetryException) {
hasRetry.set(true);
w.write("+----------------\n");
w.write("| A file operation failed.\n");
w.write("| This might be due to a file being locked by another\n");
w.write("| application. Please try closing any application\n");
w.write("| that uses the files being updated then press 'Retry'.\n");
w.write("+----------------\n");
w.write("\n\n");
}
e.printStackTrace(new PrintWriter(w));
final String content = w.getBuffer().toString();
myQueue.add(new UpdateRequest() {
@Override
public void perform() {
StringWriter w = new StringWriter();
if (!myConsolePane.isVisible()) {
@@ -411,8 +328,9 @@ public class SwingUpdaterUI implements UpdaterUI {
w.write(System.getProperty("java.io.tmpdir"));
w.write("\n\n");
}
e.printStackTrace(new PrintWriter(w));
w.append("\n");
myConsole.append(w.getBuffer().toString());
myConsole.append(content);
if (!myConsolePane.isVisible()) {
myConsole.setCaretPosition(0);
myConsolePane.setVisible(true);
@@ -423,7 +341,6 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
@Override
public void checkCancelled() throws OperationCancelledException {
if (isCancelled.get()) throw new OperationCancelledException();
}
@@ -437,8 +354,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
public static void main(String[] args) {
new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
@Override
new SwingUpdaterUI("xxx", "yyy", new InstallOperation() {
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
ui.startProcess("Process1");
ui.checkCancelled();
@@ -522,7 +438,6 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
@Override
public int getColumnCount() {
return COLUMNS.length;
}
@@ -549,7 +464,6 @@ public class SwingUpdaterUI implements UpdaterUI {
return super.getColumnClass(columnIndex);
}
@Override
public int getRowCount() {
return myItems.size();
}
@@ -566,7 +480,6 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Item item = myItems.get(rowIndex);
switch (columnIndex) {
@@ -22,6 +22,11 @@ public class UpdateAction extends BaseUpdateAction {
patchOutput.closeEntry();
}
@Override
protected boolean isModified(File toFile) throws IOException {
return myChecksum != Digester.digestRegularFile(toFile);
}
@Override
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
InputStream in = Utils.findEntryInputStream(patchFile, myPath);
@@ -153,6 +153,11 @@ public class UpdateZipAction extends BaseUpdateAction {
}
}
@Override
protected boolean isModified(File toFile) throws IOException {
return myChecksum != Digester.digestFile(toFile);
}
protected void doApply(final ZipFile patchFile, File toFile) throws IOException {
File temp = Utils.createTempFile();
FileOutputStream fileOut = new FileOutputStream(temp);
+2 -31
View File
@@ -10,19 +10,10 @@ public class Utils {
private static final byte[] BUFFER = new byte[64 * 1024];
private static File myTempDir;
public static boolean isWindows() {
return System.getProperty("os.name").startsWith("Windows");
}
public static boolean isZipFile(String fileName) {
return fileName.endsWith(".zip") || fileName.endsWith(".jar");
}
/**
* Creates a new temp file. <br/>
* All the temp files created here are located in a unique root temp directory
* that is automatically deleted by {@link #cleanup()}.
*/
@SuppressWarnings({"SSBasedInspection"})
public static File createTempFile() throws IOException {
if (myTempDir == null) {
@@ -35,12 +26,6 @@ public class Utils {
return File.createTempFile("temp.", ".tmp", myTempDir);
}
/**
* Creates a new temp directory. <br/>
* All the temp directories created here are located in a unique root temp directory
* that is automatically deleted by {@link #cleanup()}.
*/
public static File createTempDir() throws IOException {
File result = createTempFile();
delete(result);
@@ -57,15 +42,6 @@ public class Utils {
myTempDir = null;
}
/**
* Deletes a file or directory with a default timeout of 100 milliseconds.
* Directories are deleted recursively. The timeout occurs on each file.
* If one of the files fails to be deleted, the recursive directory deletion
* is aborted and not retried.
*
* @param file The file or directory to delete.
* @throws IOException
*/
public static void delete(File file) throws IOException {
if (file.isDirectory()) {
File[] files = file.listFiles();
@@ -76,20 +52,15 @@ public class Utils {
}
}
}
for (int i = 0; i < 10; i++) {
if (file.delete() || !file.exists()) {
return;
}
if (file.delete() || !file.exists()) return;
try {
Thread.sleep(10);
} catch (InterruptedException ignore) {
Runner.printStackTrace(ignore);
}
}
if (file.exists()) {
throw new IOException("Cannot delete file " + file);
}
if (file.exists()) throw new IOException("Cannot delete file " + file);
}
public static void setExecutable(File file, boolean executable) throws IOException {
@@ -24,7 +24,7 @@ public class ValidationResult implements Comparable<ValidationResult> {
}
public enum Option {
IGNORE, KEEP, REPLACE, DELETE
IGNORE, KEEP, REPLACE, DELETE, KILL_PROCESS
}
public static final String ABSENT_MESSAGE = "Absent";
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.updater;
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
public interface Win32RestartManager extends Library {
Win32RestartManager INSTANCE = (Win32RestartManager) Native.loadLibrary("Rstrtmgr", Win32RestartManager.class);
int CCH_RM_SESSION_KEY = 32;
int CCH_RM_MAX_APP_NAME = 255;
int CCH_RM_MAX_SVC_NAME = 63;
class RmUniqueProcess extends Structure {
public int dwProcessId;
public WinBase.FILETIME ProcessStartTime;
}
class RmProcessInfo extends Structure {
public RmUniqueProcess Process;
public char[] strAppName = new char[CCH_RM_MAX_APP_NAME + 1];
public char[] strServiceShortName = new char[CCH_RM_MAX_SVC_NAME + 1];
public int ApplicationType;
public WinDef.LONG AppStatus;
public int TSSessionId;
public boolean bRestartable;
}
int RmGetList(int dwSessionHandle,
IntByReference pnProcInfoNeeded,
IntByReference pnProcInfo,
RmProcessInfo rgAffectedApps,
LongByReference lpdwRebootReasons);
int RmStartSession(IntByReference pSessionHandle,
int dwSessionFlags,
char[] strSessionKey);
int RmRegisterResources(int dwSessionHandle,
int nFiles,
StringArray rgsFilenames,
int nApplications,
Pointer rgApplications,
int nServices,
StringArray rgsServiceNames);
int RmEndSession(int dwSessionHandle);
}
@@ -6,6 +6,7 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -94,6 +95,35 @@ public class PatchFileCreatorTest extends PatchTestCase {
assertNothingHasChanged(preparationResult, new HashMap<String, ValidationResult.Option>());
}
@Test
public void testRevertedWhenFileToDeleteIsProcessLocked() throws Exception {
if (!UtilsTest.mIsWindows) return;
PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
Collections.<String>emptyList(), TEST_UI);
RandomAccessFile raf = new RandomAccessFile(new File(myOlderDir, "bin/idea.bat"),"rw");
// Lock the file. FileLock is not good here, because we need to prevent deletion.
int b = raf.read();
raf.seek(0);
raf.write(b);
try {
PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
Map<String, Long> original = Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI);
File backup = getTempFile("backup");
PatchFileCreator.apply(preparationResult, new HashMap<String, ValidationResult.Option>(), backup, TEST_UI);
assertEquals(original, Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI));
}
finally {
raf.close();
}
}
@Test
public void testApplyingWithAbsentFileToDelete() throws Exception {
PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
@@ -307,6 +337,11 @@ public class PatchFileCreatorTest extends PatchTestCase {
super("_dummy_file_", -1);
}
@Override
protected boolean isModified(File toFile) throws IOException {
return false;
}
@Override
protected void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
throw new UnsupportedOperationException();
@@ -139,14 +139,16 @@ public class PatchTest extends PatchTestCase {
try {
FileLock lock = s.getChannel().lock();
try {
String message = UtilsTest.mIsWindows ? "Locked by: Java(TM) Platform SE binary" : ValidationResult.ACCESS_DENIED_MESSAGE;
ValidationResult.Option option = UtilsTest.mIsWindows ? ValidationResult.Option.KILL_PROCESS : ValidationResult.Option.IGNORE;
List<ValidationResult> result = myPatch.validate(myOlderDir, TEST_UI);
assertEquals(
new HashSet<ValidationResult>(Arrays.asList(
new ValidationResult(ValidationResult.Kind.ERROR,
"Readme.txt",
ValidationResult.Action.UPDATE,
ValidationResult.ACCESS_DENIED_MESSAGE,
ValidationResult.Option.IGNORE))),
message,
option))),
new HashSet<ValidationResult>(result));
}
finally {
@@ -23,12 +23,11 @@ import java.io.IOException;
public class UtilsTest extends TestCase {
private boolean mIsWindows;
public static boolean mIsWindows = System.getProperty("os.name").startsWith("Windows");
@Override
public void setUp() throws Exception {
super.setUp();
mIsWindows = Utils.isWindows();
}
public void testDelete() throws Exception {
+1
View File
@@ -11,6 +11,7 @@
<orderEntry type="library" name="Log4J" level="project" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="library" name="jna" level="project" />
</component>
</module>

Some files were not shown because too many files have changed in this diff Show More