mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote branch 'origin/master'
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightTestCase;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.refactoring.rename.RenameProcessor;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class RenamePackageTest extends CodeInsightTestCase {
|
||||
public void testJspImport() throws Exception {
|
||||
doTest("jspImport", "pack1", "pack2");
|
||||
}
|
||||
|
||||
public void testNonJava() throws Exception {
|
||||
doTest("nonJava", "com.foo", "fooNew");
|
||||
}
|
||||
|
||||
public void testInBrokenXml() throws Exception {
|
||||
doTest("inBrokenXml", "somepckg", "somepckg1");
|
||||
}
|
||||
|
||||
|
||||
public void testJsp() throws Exception {
|
||||
doTest("jsp", "pack1", "pack2");
|
||||
}
|
||||
|
||||
private void doTest(String testName, String packageName, String newPackageName) throws Exception {
|
||||
String root = PathManagerEx.getTestDataPath()+ "/refactoring/renamePackage/" + testName;
|
||||
|
||||
String rootBefore = root + "/before";
|
||||
PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17());
|
||||
VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, rootBefore, myFilesToDelete);
|
||||
|
||||
performAction(packageName, newPackageName);
|
||||
|
||||
String rootAfter = root + "/after";
|
||||
VirtualFile rootDir2 = LocalFileSystem.getInstance().findFileByPath(rootAfter.replace(File.separatorChar, '/'));
|
||||
IdeaTestUtil.assertDirectoriesEqual(rootDir2, rootDir, IdeaTestUtil.CVS_FILE_FILTER);
|
||||
}
|
||||
|
||||
private void performAction(String packageName, String newPackageName) throws Exception {
|
||||
PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName);
|
||||
assertNotNull("Package " + packageName + " not found", aPackage);
|
||||
|
||||
//PsiDirectory dir = aPackage.getDirectories()[0];
|
||||
//it is now impossible to rename dir without renaming corresponding package via rename processor - move processor would be used instead
|
||||
new RenameProcessor(myProject, aPackage, newPackageName, true, true).run();
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRunInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,11 @@
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class LanguageImportStatements extends LanguageExtension<ImportOptimizer> {
|
||||
public static final LanguageImportStatements INSTANCE = new LanguageImportStatements();
|
||||
@@ -29,9 +33,15 @@ public class LanguageImportStatements extends LanguageExtension<ImportOptimizer>
|
||||
super("com.intellij.lang.importOptimizer");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ImportOptimizer forFile(PsiFile file) {
|
||||
ImportOptimizer optimizer = forLanguage(file.getLanguage());
|
||||
return optimizer != null && optimizer.supports(file) ? optimizer : null;
|
||||
public List<Runnable> forFile(PsiFile file) {
|
||||
List<Runnable> runnables = new ArrayList<Runnable>();
|
||||
Set<ImportOptimizer> optimizers = new HashSet<ImportOptimizer>();
|
||||
for (PsiFile psiFile : file.getViewProvider().getAllFiles()) {
|
||||
ImportOptimizer optimizer = forLanguage(psiFile.getLanguage());
|
||||
if (optimizer != null && optimizer.supports(psiFile) && optimizers.add(optimizer)) {
|
||||
runnables.add(optimizer.processFile(psiFile));
|
||||
}
|
||||
}
|
||||
return runnables;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class LayoutCodeDialog extends DialogWrapper {
|
||||
myCbIncludeSubdirs.setEnabled(myRbDirectory.isSelected());
|
||||
myCbOptimizeImports.setEnabled(
|
||||
!myRbSelectedText.isSelected() &&
|
||||
!(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile) == null && myRbFile.isSelected()));
|
||||
!(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty() && myRbFile.isSelected()));
|
||||
|
||||
final boolean canTargetVcsChanges = canTargetVcsRegions();
|
||||
myCbOnlyVcsChangedRegions.setEnabled(canTargetVcsChanges);
|
||||
|
||||
@@ -193,6 +193,6 @@ public class OptimizeImportsAction extends AnAction {
|
||||
}
|
||||
|
||||
private static boolean isOptimizeImportsAvailable(final PsiFile file) {
|
||||
return LanguageImportStatements.INSTANCE.forFile(file) != null;
|
||||
return !LanguageImportStatements.INSTANCE.forFile(file).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
+11
-6
@@ -17,7 +17,6 @@
|
||||
package com.intellij.codeInsight.actions;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.lang.ImportOptimizer;
|
||||
import com.intellij.lang.LanguageImportStatements;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -27,6 +26,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
|
||||
@@ -58,11 +58,16 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected FutureTask<Boolean> preprocessFile(@NotNull final PsiFile file, boolean processChangedTextOnly)
|
||||
throws IncorrectOperationException
|
||||
{
|
||||
final ImportOptimizer optimizer = LanguageImportStatements.INSTANCE.forFile(file);
|
||||
Runnable runnable = optimizer != null ? optimizer.processFile(file) : EmptyRunnable.getInstance();
|
||||
protected FutureTask<Boolean> preprocessFile(@NotNull final PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException {
|
||||
final List<Runnable> optimizers = LanguageImportStatements.INSTANCE.forFile(file);
|
||||
Runnable runnable = optimizers.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Runnable optimizer : optimizers) {
|
||||
optimizer.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
return new FutureTask<Boolean>(runnable, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.ide.projectView.impl.ProjectRootsUtil;
|
||||
import com.intellij.ide.structureView.StructureView;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.structureView.StructureViewWrapper;
|
||||
import com.intellij.ide.structureView.impl.StructureViewComposite;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
@@ -43,6 +44,9 @@ import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
@@ -59,13 +63,14 @@ import java.awt.event.HierarchyListener;
|
||||
*/
|
||||
public class StructureViewWrapperImpl implements StructureViewWrapper, Disposable {
|
||||
private final Project myProject;
|
||||
private final ToolWindow myToolWindow;
|
||||
|
||||
private VirtualFile myFile;
|
||||
|
||||
private StructureView myStructureView;
|
||||
private ModuleStructureComponent myModuleStructureComponent;
|
||||
|
||||
private final JPanel myPanel;
|
||||
private JPanel[] myPanels = new JPanel[0];
|
||||
private final MergingUpdateQueue myUpdateQueue;
|
||||
private final String myKey = new String("DATA_SELECTOR");
|
||||
|
||||
@@ -75,17 +80,16 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
|
||||
private Runnable myPendingSelection;
|
||||
|
||||
public StructureViewWrapperImpl(Project project) {
|
||||
public StructureViewWrapperImpl(Project project, ToolWindow toolWindow) {
|
||||
myProject = project;
|
||||
myPanel = new ContentPanel();
|
||||
myPanel.setBackground(UIUtil.getTreeTextBackground());
|
||||
|
||||
myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myPanel, this, myPanel, true);
|
||||
myToolWindow = toolWindow;
|
||||
|
||||
myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myToolWindow.getComponent(), this, myToolWindow.getComponent(), true);
|
||||
myUpdateQueue.setRestartTimerOnAdd(true);
|
||||
|
||||
ActionManager.getInstance().addTimerListener(500, new TimerListener() {
|
||||
public ModalityState getModalityState() {
|
||||
return ModalityState.stateForComponent(myPanel);
|
||||
return ModalityState.stateForComponent(myToolWindow.getComponent());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
@@ -93,20 +97,21 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
}
|
||||
});
|
||||
|
||||
getComponent().addHierarchyListener(new HierarchyListener() {
|
||||
myToolWindow.getComponent().addHierarchyListener(new HierarchyListener() {
|
||||
public void hierarchyChanged(HierarchyEvent e) {
|
||||
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
|
||||
scheduleRebuild();
|
||||
}
|
||||
}
|
||||
});
|
||||
Disposer.register(myToolWindow.getContentManager(), this);
|
||||
}
|
||||
|
||||
private void checkUpdate() {
|
||||
if (myProject.isDisposed()) return;
|
||||
|
||||
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
if (SwingUtilities.isDescendingFrom(myPanel, owner) || JBPopupFactory.getInstance().isPopupActive()) return;
|
||||
if (SwingUtilities.isDescendingFrom(myToolWindow.getComponent(), owner) || JBPopupFactory.getInstance().isPopupActive()) return;
|
||||
|
||||
final DataContext dataContext = DataManager.getInstance().getDataContext(owner);
|
||||
if (dataContext.getData(myKey) == this) return;
|
||||
@@ -133,10 +138,6 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
// StructureView interface implementation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public JComponent getComponent() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
rebuild();
|
||||
}
|
||||
@@ -202,8 +203,8 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
myModuleStructureComponent = null;
|
||||
}
|
||||
|
||||
myPanel.removeAll();
|
||||
|
||||
final ContentManager contentManager = myToolWindow.getContentManager();
|
||||
contentManager.removeAllContents(true);
|
||||
if (!isStructureViewShowing()) {
|
||||
return;
|
||||
}
|
||||
@@ -216,19 +217,16 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
}
|
||||
}
|
||||
|
||||
String[] names = new String[] {""};
|
||||
JComponent focusedComponent = null;
|
||||
if (file != null && file.isValid()) {
|
||||
if (file.isDirectory()) {
|
||||
if (ProjectRootsUtil.isModuleContentRoot(file, myProject)) {
|
||||
Module module = ModuleUtil.findModuleForFile(file, myProject);
|
||||
if (module != null) {
|
||||
myModuleStructureComponent = new ModuleStructureComponent(module);
|
||||
myPanel.add(myModuleStructureComponent, BorderLayout.CENTER);
|
||||
if (hadFocus) {
|
||||
JComponent focusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent);
|
||||
if (focusedComponent != null) {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
|
||||
}
|
||||
}
|
||||
focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent) : null;
|
||||
createSinglePanel(myModuleStructureComponent.getComponent());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,13 +244,22 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
if (myStructureView instanceof StructureView.Scrollable) {
|
||||
((StructureView.Scrollable)myStructureView).setReferenceSizeWhileInitializing(referenceSize);
|
||||
}
|
||||
myPanel.add(myStructureView.getComponent(), BorderLayout.CENTER);
|
||||
if (hadFocus) {
|
||||
JComponent focusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myStructureView.getComponent());
|
||||
if (focusedComponent != null) {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
|
||||
|
||||
final StructureViewComposite.StructureViewDescriptor[] views;
|
||||
|
||||
if (myStructureView instanceof StructureViewComposite) {
|
||||
final StructureViewComposite composite = (StructureViewComposite)myStructureView;
|
||||
views = composite.getStructureViews();
|
||||
myPanels = new JPanel[views.length];
|
||||
names = new String[views.length];
|
||||
for (int i = 0; i < myPanels.length; i++) {
|
||||
myPanels[i] = createContentPanel(views[i].structureView.getComponent());
|
||||
names[i] = views[i].title;
|
||||
}
|
||||
} else {
|
||||
createSinglePanel(myStructureView.getComponent());
|
||||
}
|
||||
focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myStructureView.getComponent()) : null;
|
||||
myStructureView.restoreState();
|
||||
myStructureView.centerSelectedRow();
|
||||
}
|
||||
@@ -264,11 +271,19 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
}
|
||||
|
||||
if (myModuleStructureComponent == null && myStructureView == null) {
|
||||
myPanel.add(new JLabel(IdeBundle.message("message.nothing.to.show.in.structure.view"), SwingConstants.CENTER), BorderLayout.CENTER);
|
||||
createSinglePanel(new JLabel(IdeBundle.message("message.nothing.to.show.in.structure.view"), SwingConstants.CENTER));
|
||||
}
|
||||
|
||||
myPanel.validate();
|
||||
myPanel.repaint();
|
||||
for (int i = 0; i < myPanels.length; i++) {
|
||||
final Content content = ContentFactory.SERVICE.getInstance().createContent(myPanels[i], names[i], false);
|
||||
contentManager.addContent(content);
|
||||
if (i == 0 && myStructureView != null) {
|
||||
Disposer.register(content, myStructureView);
|
||||
}
|
||||
}
|
||||
if (hadFocus && focusedComponent != null) {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
|
||||
}
|
||||
|
||||
if (myPendingSelection != null) {
|
||||
Runnable selection = myPendingSelection;
|
||||
@@ -277,6 +292,18 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
}
|
||||
}
|
||||
|
||||
private void createSinglePanel(final JComponent component) {
|
||||
myPanels = new JPanel[1];
|
||||
myPanels[0] = createContentPanel(component);
|
||||
}
|
||||
|
||||
private ContentPanel createContentPanel(JComponent component) {
|
||||
final ContentPanel panel = new ContentPanel();
|
||||
panel.setBackground(UIUtil.getTreeTextBackground());
|
||||
panel.add(component, BorderLayout.CENTER);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FileEditor createTempFileEditor(VirtualFile file) {
|
||||
FileEditorProviderManager editorProviderManager = FileEditorProviderManager.getInstance();
|
||||
|
||||
+1
-17
@@ -20,12 +20,9 @@ import com.intellij.ide.structureView.StructureView;
|
||||
import com.intellij.ide.structureView.StructureViewModel;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.TabbedPaneWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
@@ -33,8 +30,6 @@ import javax.swing.event.ChangeListener;
|
||||
public class StructureViewComposite implements StructureView {
|
||||
@NotNull private final StructureViewDescriptor[] myStructureViews;
|
||||
@NotNull private StructureViewDescriptor mySelectedViewDescriptor;
|
||||
@NotNull private final TabbedPaneWrapper myTabbedPaneWrapper;
|
||||
|
||||
public static class StructureViewDescriptor {
|
||||
public final String title;
|
||||
public final StructureView structureView;
|
||||
@@ -53,17 +48,6 @@ public class StructureViewComposite implements StructureView {
|
||||
Disposer.register(this, descriptor.structureView);
|
||||
}
|
||||
mySelectedViewDescriptor = views[0];
|
||||
myTabbedPaneWrapper = new TabbedPaneWrapper(this);
|
||||
for (StructureViewDescriptor descriptor : views) {
|
||||
myTabbedPaneWrapper.addTab(descriptor.title, descriptor.icon, descriptor.structureView.getComponent(), null);
|
||||
}
|
||||
myTabbedPaneWrapper.setSelectedIndex(0);
|
||||
myTabbedPaneWrapper.addChangeListener(new ChangeListener() {
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
int index = myTabbedPaneWrapper.getSelectedIndex();
|
||||
mySelectedViewDescriptor = myStructureViews[index];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public StructureView getSelectedStructureView() {
|
||||
@@ -84,7 +68,7 @@ public class StructureViewComposite implements StructureView {
|
||||
}
|
||||
|
||||
public JComponent getComponent() {
|
||||
return myTabbedPaneWrapper.getComponent();
|
||||
return mySelectedViewDescriptor.structureView.getComponent();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
||||
+1
-8
@@ -25,14 +25,11 @@ import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.MultiValuesMap;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -96,11 +93,7 @@ public final class StructureViewFactoryImpl extends StructureViewFactoryEx imple
|
||||
}
|
||||
|
||||
public void initToolWindow(ToolWindow toolWindow) {
|
||||
myStructureViewWrapperImpl = new StructureViewWrapperImpl(myProject);
|
||||
final Content content = ContentFactory.SERVICE.getInstance().createContent(myStructureViewWrapperImpl.getComponent(), "", false);
|
||||
Disposer.register(content, myStructureViewWrapperImpl);
|
||||
toolWindow.getContentManager().addContent(content);
|
||||
|
||||
myStructureViewWrapperImpl = new StructureViewWrapperImpl(myProject, toolWindow);
|
||||
if (myRunWhenInitialized != null) {
|
||||
myRunWhenInitialized.run();
|
||||
myRunWhenInitialized = null;
|
||||
|
||||
@@ -130,12 +130,12 @@ public class LogMessageEx extends LogMessage {
|
||||
};
|
||||
}
|
||||
|
||||
public static void error(@NotNull Logger logger, @NotNull String message, @NotNull String... details) {
|
||||
public static void error(@NotNull Logger logger, @NotNull String message, @NotNull String... attachmentText) {
|
||||
StringBuilder detailsBuffer = new StringBuilder();
|
||||
for (String detail : details) {
|
||||
for (String detail : attachmentText) {
|
||||
detailsBuffer.append(detail).append(",");
|
||||
}
|
||||
if (details.length > 0 && detailsBuffer.length() > 0) {
|
||||
if (attachmentText.length > 0 && detailsBuffer.length() > 0) {
|
||||
detailsBuffer.setLength(detailsBuffer.length() - 1);
|
||||
}
|
||||
Attachment attachment = detailsBuffer.length() > 0 ? new Attachment("current-context.txt", detailsBuffer.toString()) : null;
|
||||
|
||||
+29
-14
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl.softwrap.mapping;
|
||||
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
@@ -24,10 +26,7 @@ import com.intellij.openapi.editor.event.VisibleAreaListener;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.ScrollingModelEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
|
||||
import com.intellij.openapi.editor.impl.FontInfo;
|
||||
import com.intellij.openapi.editor.impl.IterationState;
|
||||
import com.intellij.openapi.editor.impl.TextChangeImpl;
|
||||
import com.intellij.openapi.editor.impl.*;
|
||||
import com.intellij.openapi.editor.impl.softwrap.*;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -54,7 +53,9 @@ import java.util.List;
|
||||
* @since Jul 5, 2010 10:01:27 AM
|
||||
*/
|
||||
public class SoftWrapApplianceManager implements SoftWrapFoldingListener, DocumentListener {
|
||||
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + SoftWrapApplianceManager.class.getName());
|
||||
|
||||
/** Enumerates possible type of soft wrap indents to use. */
|
||||
enum IndentType {
|
||||
/** Don't apply special indent to soft-wrapped line at all. */
|
||||
@@ -90,14 +91,15 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
*/
|
||||
private int myLastTopLeftCornerOffset = -1;
|
||||
|
||||
private VisibleAreaWidthProvider myWidthProvider;
|
||||
private LineWrapPositionStrategy myLineWrapPositionStrategy;
|
||||
private boolean myVisualAreaListenerAttached;
|
||||
private boolean myCustomIndentUsedLastTime;
|
||||
private int myCustomIndentValueUsedLastTime;
|
||||
private int myVisibleAreaWidth;
|
||||
private boolean myInProgress;
|
||||
private boolean myHasLinesWithFailedWrap;
|
||||
private VisibleAreaWidthProvider myWidthProvider;
|
||||
private LineWrapPositionStrategy myLineWrapPositionStrategy;
|
||||
private IncrementalCacheUpdateEvent myEventBeingProcessed;
|
||||
private boolean myVisualAreaListenerAttached;
|
||||
private boolean myCustomIndentUsedLastTime;
|
||||
private int myCustomIndentValueUsedLastTime;
|
||||
private int myVisibleAreaWidth;
|
||||
private boolean myInProgress;
|
||||
private boolean myHasLinesWithFailedWrap;
|
||||
|
||||
public SoftWrapApplianceManager(@NotNull SoftWrapsStorage storage,
|
||||
@NotNull EditorEx editor,
|
||||
@@ -172,16 +174,28 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
List<IncrementalCacheUpdateEvent> events = new ArrayList<IncrementalCacheUpdateEvent>(myEventsStorage.getEvents());
|
||||
myActiveEvents.addAll(events);
|
||||
myEventsStorage.release();
|
||||
if (myInProgress && !events.isEmpty()) {
|
||||
String state = "";
|
||||
if (myEditor instanceof EditorImpl) {
|
||||
state = ((EditorImpl)myEditor).dumpState();
|
||||
}
|
||||
LogMessageEx.error(LOG, "Detected race condition at soft wraps recalculation", String.format(
|
||||
"Current events: %s. Concurrent events: %s, event being processed: %s%n%s",
|
||||
events, myActiveEvents, myEventBeingProcessed, state
|
||||
));
|
||||
}
|
||||
myInProgress = true;
|
||||
myHasLinesWithFailedWrap = false;
|
||||
try {
|
||||
for (IncrementalCacheUpdateEvent event : events) {
|
||||
myEventBeingProcessed = event;
|
||||
recalculateSoftWraps(event);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myInProgress = false;
|
||||
myActiveEvents.clear();
|
||||
myEventBeingProcessed = null;
|
||||
}
|
||||
updateLastTopLeftCornerOffset();
|
||||
return true;
|
||||
@@ -896,7 +910,8 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"recalculation in progress: %b; stored update events: %s; active update events: %s", myInProgress, myEventsStorage, myActiveEvents
|
||||
"recalculation in progress: %b; stored update events: %s; active update events: %s, event being processed: %s",
|
||||
myInProgress, myEventsStorage, myActiveEvents, myEventBeingProcessed
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -565,8 +565,8 @@ action.structureview.show.non.public=Show non-public
|
||||
node.structureview.invalid=<invalid>
|
||||
action.structureview.group.methods.by.defining.type=Group Methods by Defining Type
|
||||
action.structureview.sort.by.visibility=Sort by Visibility
|
||||
tab.structureview.jsp.view=JSP View
|
||||
tab.structureview.baselanguage.view={0} View
|
||||
tab.structureview.jsp.view=JSP
|
||||
tab.structureview.baselanguage.view={0}
|
||||
action.next.todo=Next TODO
|
||||
action.previous.todo=Previous TODO
|
||||
action.filter.todo.items=Filter TODO Items
|
||||
|
||||
@@ -415,12 +415,16 @@ public abstract class VcsVFSListener implements Disposable {
|
||||
checkMovedAddedSourceBack();
|
||||
if (!myAddedFiles.isEmpty()) {
|
||||
executeAdd();
|
||||
myAddedFiles.clear();
|
||||
}
|
||||
if (!myDeletedFiles.isEmpty() || !myDeletedWithoutConfirmFiles.isEmpty()) {
|
||||
executeDelete();
|
||||
myDeletedFiles.clear();
|
||||
myDeletedWithoutConfirmFiles.clear();
|
||||
}
|
||||
if (!myMovedFiles.isEmpty()) {
|
||||
executeMoveRename();
|
||||
myMovedFiles.clear();
|
||||
}
|
||||
if (! myDirtyFiles.isEmpty()) {
|
||||
final List<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
|
||||
@@ -28,6 +28,9 @@ import com.intellij.openapi.vcs.VcsDirectoryMapping;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class StartUseVcsAction extends AnAction implements DumbAware {
|
||||
public StartUseVcsAction() {
|
||||
super(VcsBundle.message("action.enable.version.control.integration.text"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
|
||||
@@ -391,14 +391,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
myUpdateException = null;
|
||||
myAdditionalInfo.clear();
|
||||
}
|
||||
debugLogging("refresh procedure started, everything = " + wasEverythingDirty + " dirty scope: " +
|
||||
StringUtil.join(scopes, new Function<VcsDirtyScope, String>() {
|
||||
@Override
|
||||
public String fun(VcsDirtyScope scope) {
|
||||
return scope.toString();
|
||||
}
|
||||
}, "->\n"));
|
||||
}
|
||||
final String scopeInString = (! LOG.isDebugEnabled()) ? "" : StringUtil.join(scopes, new Function<VcsDirtyScope, String>() {
|
||||
@Override
|
||||
public String fun(VcsDirtyScope scope) {
|
||||
return scope.toString();
|
||||
}
|
||||
}, "->\n");
|
||||
debugLogging("refresh procedure started, everything = " + wasEverythingDirty + " dirty scope: " + scopeInString);
|
||||
dataHolder.notifyStart();
|
||||
myChangesViewManager.scheduleRefresh();
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import git4idea.remote.GitRememberedInputs;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.update.GitFetchResult;
|
||||
import git4idea.util.NetrcData;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
@@ -43,6 +44,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URISyntaxException;
|
||||
@@ -65,9 +67,27 @@ public final class GitHttpAdapter {
|
||||
|
||||
public static boolean isHttpUrlWithoutUserCredentials(@NotNull String url) {
|
||||
// if username & password are specified in the url, give it to the native Git
|
||||
return url.startsWith("http") && !HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches();
|
||||
if (!url.startsWith("http")) {
|
||||
return false;
|
||||
}
|
||||
if (HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
NetrcData netrcData = NetrcData.parse();
|
||||
return !netrcData.hasAuthDataForUrl(url);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("Couldn't read netrc file", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum GeneralResult {
|
||||
SUCCESS,
|
||||
CANCELLED,
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.util;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Parses {@code .netrc} file and stores the parsed authentication information in {@link AuthRecord} objects.
|
||||
* Parse only {@code machine}, {@code login} and {@code password} fields.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class NetrcData {
|
||||
|
||||
private static final String NETRC_FILE = SystemInfo.isWindows ? "_netrc" : ".netrc";
|
||||
private final Map<String, AuthRecord> myAuthDataMap;
|
||||
|
||||
private NetrcData(@NotNull Map<String, AuthRecord> authData) {
|
||||
myAuthDataMap = authData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@code .netrc} file (which is {@code _netrc} on Windows) and returns the NetrcData object which can be analyzed further.
|
||||
*/
|
||||
@NotNull
|
||||
public static NetrcData parse() throws IOException {
|
||||
String home = SystemProperties.getUserHome();
|
||||
File netrc = new File(home, NETRC_FILE);
|
||||
return parse(netrc);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static NetrcData parse(@NotNull File netrcFile) throws IOException {
|
||||
if (!netrcFile.exists()) {
|
||||
throw new FileNotFoundException(netrcFile.getPath());
|
||||
}
|
||||
String netrcContent = FileUtil.loadFile(netrcFile);
|
||||
return parse(netrcContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff the host of the given url is contained in {@code .netrc}, and both login and password are set for this host.
|
||||
*/
|
||||
public boolean hasAuthDataForUrl(@NotNull String url) {
|
||||
String host = getHostFromUrl(url);
|
||||
AuthRecord authRecord = myAuthDataMap.get(host);
|
||||
return authRecord != null && authRecord.getLogin() != null && authRecord.getPassword() != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Collection<AuthRecord> getAuthData() {
|
||||
return myAuthDataMap.values();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getHostFromUrl(@NotNull String url) {
|
||||
final String schemaSeparator = "://";
|
||||
String urlWithoutSchema = url.substring(url.indexOf(schemaSeparator) + schemaSeparator.length());
|
||||
return urlWithoutSchema.substring(0, urlWithoutSchema.indexOf('/'));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static NetrcData parse(@NotNull String content) {
|
||||
Map<String, AuthRecord> result = new HashMap<String, AuthRecord>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(content);
|
||||
AuthRecord currentRecord = null;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String token = tokenizer.nextToken();
|
||||
if (token.equalsIgnoreCase("machine")) {
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
break;
|
||||
}
|
||||
String host = tokenizer.nextToken();
|
||||
host = host.toLowerCase(); // hosts are case insensitive
|
||||
if (result.containsKey(host)) {
|
||||
currentRecord = result.get(host);
|
||||
} else {
|
||||
currentRecord = new AuthRecord(host);
|
||||
result.put(host, currentRecord);
|
||||
}
|
||||
}
|
||||
else if (token.equalsIgnoreCase("login")) {
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
break;
|
||||
}
|
||||
if (currentRecord != null && currentRecord.getLogin() == null) {
|
||||
currentRecord.setLogin(tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
else if (token.equalsIgnoreCase("password")) {
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
break;
|
||||
}
|
||||
if (currentRecord != null && currentRecord.getPassword() == null) {
|
||||
currentRecord.setPassword(tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new NetrcData(result);
|
||||
}
|
||||
|
||||
static class AuthRecord {
|
||||
private final String myHost;
|
||||
private String myLogin;
|
||||
private String myPassword;
|
||||
|
||||
AuthRecord(String host, String login, String password) {
|
||||
myHost = host;
|
||||
myLogin = login;
|
||||
myPassword = password;
|
||||
}
|
||||
|
||||
private AuthRecord(String host) {
|
||||
myHost = host;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getLogin() {
|
||||
return myLogin;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getPassword() {
|
||||
return myPassword;
|
||||
}
|
||||
|
||||
private void setLogin(String login) {
|
||||
myLogin = login;
|
||||
}
|
||||
|
||||
private void setPassword(String password) {
|
||||
myPassword = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("AuthRecord{host=%s, login=%s, password=%s}", myHost, myLogin, myPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AuthRecord record = (AuthRecord)o;
|
||||
|
||||
if (myHost != null ? !myHost.equalsIgnoreCase(record.myHost) : record.myHost != null) return false; // NB: host is case insensitive
|
||||
if (myLogin != null ? !myLogin.equals(record.myLogin) : record.myLogin != null) return false;
|
||||
if (myPassword != null ? !myPassword.equals(record.myPassword) : record.myPassword != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myHost != null ? myHost.hashCode() : 0;
|
||||
result = 31 * result + (myLogin != null ? myLogin.hashCode() : 0);
|
||||
result = 31 * result + (myPassword != null ? myPassword.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
n0 empty netrc
|
||||
@@ -0,0 +1,2 @@
|
||||
machine bitbucket.org
|
||||
login john
|
||||
@@ -0,0 +1 @@
|
||||
n1 just login for machine
|
||||
@@ -0,0 +1 @@
|
||||
bitbucket.org john
|
||||
@@ -0,0 +1,3 @@
|
||||
machine bitbucket.org
|
||||
login john
|
||||
password pass
|
||||
@@ -0,0 +1 @@
|
||||
n2 login & password defined
|
||||
@@ -0,0 +1 @@
|
||||
bitbucket.org john pass
|
||||
@@ -0,0 +1,6 @@
|
||||
machine bitbucket.org
|
||||
login john
|
||||
password pass
|
||||
machine github.com
|
||||
login bob
|
||||
password pswd
|
||||
@@ -0,0 +1 @@
|
||||
n3 two full standard hosts
|
||||
@@ -0,0 +1,2 @@
|
||||
bitbucket.org john pass
|
||||
github.com bob pswd
|
||||
@@ -0,0 +1,4 @@
|
||||
machine bitbucket.org
|
||||
login john
|
||||
machine bitbucket.org
|
||||
password pass
|
||||
@@ -0,0 +1,2 @@
|
||||
n4 two supplementary records for one host
|
||||
One host defined twice, login is set in the first record, password - in the second => complete auth data should be read
|
||||
@@ -0,0 +1 @@
|
||||
bitbucket.org john pass
|
||||
@@ -0,0 +1,5 @@
|
||||
machine bitbucket.org
|
||||
login john
|
||||
password pass
|
||||
machine bitbucket.org
|
||||
password doesnt_override
|
||||
@@ -0,0 +1 @@
|
||||
n5 overriding records for 1 host
|
||||
@@ -0,0 +1 @@
|
||||
bitbucket.org john pass
|
||||
@@ -0,0 +1,4 @@
|
||||
machine
|
||||
bitbucket.org
|
||||
login
|
||||
john password pass
|
||||
@@ -0,0 +1 @@
|
||||
n6 poorly formatted netrc for 1 host
|
||||
@@ -0,0 +1 @@
|
||||
bitbucket.org john pass
|
||||
@@ -15,71 +15,34 @@
|
||||
*/
|
||||
package git4idea.repo;
|
||||
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import git4idea.tests.GitTestUtil;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitConfigTest {
|
||||
|
||||
|
||||
@DataProvider(name = "remote")
|
||||
public Object[][] loadRemotes() throws IOException {
|
||||
return loadData("remote");
|
||||
return GitTestUtil.loadConfigData(getTestDataFolder("remote"));
|
||||
}
|
||||
|
||||
@DataProvider(name = "branch")
|
||||
public Object[][] loadBranches() throws IOException {
|
||||
return loadData("branch");
|
||||
return GitTestUtil.loadConfigData(getTestDataFolder("branch"));
|
||||
}
|
||||
|
||||
public static Object[][] loadData(String subfolder) throws IOException {
|
||||
File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea"));
|
||||
File dataDir = new File(new File(new File(pluginRoot, "testData"), "config"), subfolder);
|
||||
File[] tests = dataDir.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return !name.startsWith(".");
|
||||
}
|
||||
});
|
||||
Object[][] data = new Object[tests.length][];
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
File testDir = tests[i];
|
||||
File descriptionFile = null;
|
||||
File configFile = null;
|
||||
File resultFile = null;
|
||||
for (File file : testDir.listFiles()) {
|
||||
if (file.getName().endsWith("_desc.txt")) {
|
||||
descriptionFile = file;
|
||||
}
|
||||
else if (file.getName().endsWith("_config.txt")) {
|
||||
configFile = file;
|
||||
}
|
||||
else if (file.getName().endsWith("_result.txt")) {
|
||||
resultFile = file;
|
||||
}
|
||||
}
|
||||
assertNotNull(descriptionFile, String.format("description file not found in %s among %s", testDir, Arrays.toString(testDir.list())));
|
||||
assertNotNull(configFile, String.format("config file file not found in %s among %s", testDir, Arrays.toString(testDir.list())));
|
||||
assertNotNull(resultFile, String.format("result file file not found in %s among %s", testDir, Arrays.toString(testDir.list())));
|
||||
|
||||
String testName = FileUtil.loadFile(descriptionFile).split("\n")[0]; // description is in the first line of the desc-file
|
||||
data[i] = new Object[]{
|
||||
testName, configFile, resultFile
|
||||
};
|
||||
}
|
||||
return data;
|
||||
private static File getTestDataFolder(String subfolder) {
|
||||
File testData = GitTestUtil.getTestDataFolder();
|
||||
return new File(new File(testData, "config"), subfolder);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "remote")
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.testFramework.LightIdeaTestCase;
|
||||
import com.intellij.util.Processor;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.branch.GitBranchesCollection;
|
||||
import git4idea.tests.GitTestUtil;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
+49
-1
@@ -13,21 +13,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.tests;
|
||||
package git4idea.test;
|
||||
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.tests.GitTestRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
@@ -171,6 +178,47 @@ public class GitTestUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Object[][] loadConfigData(@NotNull File dataFolder) throws IOException {
|
||||
File[] tests = dataFolder.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return !name.startsWith(".");
|
||||
}
|
||||
});
|
||||
Object[][] data = new Object[tests.length][];
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
File testDir = tests[i];
|
||||
File descriptionFile = null;
|
||||
File configFile = null;
|
||||
File resultFile = null;
|
||||
for (File file : testDir.listFiles()) {
|
||||
if (file.getName().endsWith("_desc.txt")) {
|
||||
descriptionFile = file;
|
||||
}
|
||||
else if (file.getName().endsWith("_config.txt")) {
|
||||
configFile = file;
|
||||
}
|
||||
else if (file.getName().endsWith("_result.txt")) {
|
||||
resultFile = file;
|
||||
}
|
||||
}
|
||||
assertNotNull(descriptionFile, String.format("description file not found in %s among %s", testDir, Arrays.toString(testDir.list())));
|
||||
assertNotNull(configFile, String.format("config file file not found in %s among %s", testDir, Arrays.toString(testDir.list())));
|
||||
assertNotNull(resultFile, String.format("result file file not found in %s among %s", testDir, Arrays.toString(testDir.list())));
|
||||
|
||||
String testName = FileUtil.loadFile(descriptionFile).split("\n")[0]; // description is in the first line of the desc-file
|
||||
data[i] = new Object[]{
|
||||
testName, configFile, resultFile
|
||||
};
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static File getTestDataFolder() {
|
||||
File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea"));
|
||||
return new File(pluginRoot, "testData");
|
||||
}
|
||||
|
||||
public interface EqualityChecker<T, E> {
|
||||
boolean areEqual(T actual, E expected);
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package git4idea.tests;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.testFramework.vcs.MockChangelistBuilder;
|
||||
import com.intellij.testFramework.vcs.MockDirtyScope;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.status.GitChangeProvider;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.util;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class NetrcDataTest {
|
||||
|
||||
@DataProvider(name = "netrc")
|
||||
public Object[][] loadBranches() throws IOException {
|
||||
return GitTestUtil.loadConfigData(new File(GitTestUtil.getTestDataFolder(), "netrc"));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "netrc")
|
||||
public void testBranches(String testName, File netrcFile, File resultFile) throws IOException {
|
||||
NetrcData netrcData = NetrcData.parse(netrcFile);
|
||||
Collection<NetrcData.AuthRecord> expectedRecord = readAuthData(resultFile);
|
||||
GitTestUtil.assertEqualCollections(netrcData.getAuthData(), expectedRecord);
|
||||
|
||||
if (!testName.startsWith("n0") && !testName.startsWith("n1")) { // auth data not defined for these tests
|
||||
assertTrue(netrcData.hasAuthDataForUrl("http://bitbucket.org"));
|
||||
assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org"));
|
||||
assertTrue(netrcData.hasAuthDataForUrl("bitbucket.org"));
|
||||
assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org/user/repo.git"));
|
||||
assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org/user/repo"));
|
||||
}
|
||||
|
||||
assertFalse(netrcData.hasAuthDataForUrl("http://example.com"));
|
||||
assertFalse(netrcData.hasAuthDataForUrl("https://example.com"));
|
||||
assertFalse(netrcData.hasAuthDataForUrl("example.com"));
|
||||
}
|
||||
|
||||
private static Collection<NetrcData.AuthRecord> readAuthData(File file) throws IOException {
|
||||
Collection<NetrcData.AuthRecord> authRecords = new ArrayList<NetrcData.AuthRecord>();
|
||||
for (String authLine : FileUtil.loadFile(file).split("\n")) {
|
||||
if (StringUtil.isEmptyOrSpaces(authLine)) {
|
||||
continue;
|
||||
}
|
||||
String[] data = authLine.split(" ");
|
||||
authRecords.add(new NetrcData.AuthRecord(data[0], data[1], data.length > 2 ? data[2] : null));
|
||||
}
|
||||
return authRecords;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ package org.zmlx.hg4idea.execution;
|
||||
import com.intellij.execution.process.CapturingProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -44,8 +44,12 @@ public final class ShellCommand {
|
||||
if (myRunViaBash) {
|
||||
// run via bash -cl <hg command> => need to escape bash special symbols
|
||||
// '-l' makes bash execute as a login shell thus reading .bash_profile
|
||||
String hgCommand = StringUtil.join(commandLine, " ");
|
||||
hgCommand = escapeBashControlCharacters(hgCommand);
|
||||
StringBuilder hgCommandBuilder = new StringBuilder();
|
||||
for (String command : commandLine) {
|
||||
hgCommandBuilder.append(escapeSpacesIfNeeded(command));
|
||||
hgCommandBuilder.append(" ");
|
||||
}
|
||||
String hgCommand = escapeBashControlCharacters(hgCommandBuilder.toString());
|
||||
commandLine = new ArrayList<String>(3);
|
||||
commandLine.add("bash");
|
||||
commandLine.add("-cl");
|
||||
@@ -100,4 +104,9 @@ public final class ShellCommand {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String escapeSpacesIfNeeded(@NotNull String s) {
|
||||
return myRunViaBash ? s.replace(" ", "\\ ") : s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-6
@@ -73,21 +73,21 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool
|
||||
XmlAttributeValue value = attribute.getValueElement();
|
||||
assert value != null;
|
||||
holder.registerProblem(attribute, "Namespace declaration is never used", ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
new RemoveNamespaceDeclarationFix(declaredPrefix));
|
||||
new RemoveNamespaceDeclarationFix(declaredPrefix, false));
|
||||
|
||||
XmlTag parent = attribute.getParent();
|
||||
if (declaredPrefix.length() == 0) {
|
||||
XmlAttribute location = getDefaultLocation(parent);
|
||||
if (location != null) {
|
||||
holder.registerProblem(location, NAMESPACE_LOCATION_IS_NEVER_USED, ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
new RemoveNamespaceDeclarationFix(declaredPrefix));
|
||||
new RemoveNamespaceDeclarationFix(declaredPrefix, true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (PsiReference reference : getLocationReferences(namespace, parent)) {
|
||||
if (!XmlHighlightVisitor.hasBadResolve(reference, false))
|
||||
holder.registerProblemForReference(reference, ProblemHighlightType.LIKE_UNUSED_SYMBOL, NAMESPACE_LOCATION_IS_NEVER_USED,
|
||||
new RemoveNamespaceDeclarationFix(declaredPrefix));
|
||||
new RemoveNamespaceDeclarationFix(declaredPrefix, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,9 +234,11 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool
|
||||
public static final String NAME = "Remove unused namespace declaration";
|
||||
|
||||
protected final String myPrefix;
|
||||
private final boolean myLocationFix;
|
||||
|
||||
private RemoveNamespaceDeclarationFix(@Nullable String prefix) {
|
||||
private RemoveNamespaceDeclarationFix(@Nullable String prefix, boolean locationFix) {
|
||||
myPrefix = prefix;
|
||||
myLocationFix = locationFix;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -328,7 +330,9 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof RemoveNamespaceDeclarationFix && Comparing.equal(myPrefix, ((RemoveNamespaceDeclarationFix)obj).myPrefix);
|
||||
return obj instanceof RemoveNamespaceDeclarationFix &&
|
||||
Comparing.equal(myPrefix, ((RemoveNamespaceDeclarationFix)obj).myPrefix) &&
|
||||
(myLocationFix || ((RemoveNamespaceDeclarationFix)obj).myLocationFix);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -342,7 +346,7 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool
|
||||
public static final String NAME = "Remove unused namespace location";
|
||||
|
||||
private RemoveNamespaceLocationFix(String namespace) {
|
||||
super(namespace);
|
||||
super(namespace, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user