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:
@@ -50,9 +50,9 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
|
||||
myCbUseCompileServer.setVisible(ApplicationManager.getApplication().isInternal());
|
||||
myPatternLegendLabel.setText("<html>" +
|
||||
"Use <b>;</b> to separate patterns and <b>!</b> to negate a pattern.<br/>" +
|
||||
"Accepted wildcards: <b>?</b> - exactly one symbol; <b>*</b> - zero or more symbols;<br/>" +
|
||||
" <b>/</b> - path separator; <b>/**/</b> - any number of directories;<br>" +
|
||||
" <i>resources</i>:* - for everything under a source root named <i>resources</i>" +
|
||||
"Accepted wildcards: <b>?</b> — exactly one symbol; <b>*</b> — zero or more symbols;<br/>" +
|
||||
" <b>/</b> — path separator; <b>/**/</b> — any number of directories;<br>" +
|
||||
" <i><dir_name></i>:<pattern> — restrict to source roots with the specified name" +
|
||||
"</html>");
|
||||
}
|
||||
|
||||
|
||||
+15
-65
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -15,75 +15,33 @@
|
||||
*/
|
||||
package com.intellij.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.SourcePosition;
|
||||
import com.intellij.debugger.engine.RequestHint;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.containers.OrderedSet;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SmartStepIntoActionHandler extends DebuggerActionHandler {
|
||||
public void perform(@NotNull final Project project, final AnActionEvent event) {
|
||||
final DebuggerContextImpl debuggerContext = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
doStep(project, debuggerContext.getSourcePosition(), debuggerContext.getDebuggerSession());
|
||||
/**
|
||||
* User: Alexander Podkhalyuzin
|
||||
* Date: 22.11.11
|
||||
*/
|
||||
public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
@Override
|
||||
public boolean isAvailable(final SourcePosition position) {
|
||||
final PsiFile file = position.getFile();
|
||||
return file.getLanguage().isKindOf(JavaLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
private static void doStep(final @NotNull Project project, final @Nullable SourcePosition position, final @NotNull DebuggerSession session) {
|
||||
final VirtualFile file = position != null ? position.getFile().getVirtualFile() : null;
|
||||
final FileEditor fileEditor = file != null? FileEditorManager.getInstance(project).getSelectedEditor(file) : null;
|
||||
if (fileEditor instanceof TextEditor) {
|
||||
final List<PsiMethod> methods = findReferencedMethods(position);
|
||||
if (methods.size() > 0) {
|
||||
if (methods.size() == 1) {
|
||||
session.stepInto(true, createSmartStepFilter(methods.get(0)));
|
||||
}
|
||||
else {
|
||||
final PsiMethodListPopupStep popupStep = new PsiMethodListPopupStep(methods, new PsiMethodListPopupStep.OnChooseRunnable() {
|
||||
public void execute(PsiMethod chosenMethod) {
|
||||
session.stepInto(true, createSmartStepFilter(chosenMethod));
|
||||
}
|
||||
});
|
||||
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(popupStep);
|
||||
final RelativePoint point = DebuggerUIUtil.calcPopupLocation(((TextEditor)fileEditor).getEditor(), position.getLine());
|
||||
popup.show(point);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
session.stepInto(true, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static RequestHint.SmartStepFilter createSmartStepFilter(final PsiMethod method) {
|
||||
return new RequestHint.SmartStepFilter(method);
|
||||
}
|
||||
|
||||
|
||||
private static List<PsiMethod> findReferencedMethods(final SourcePosition position) {
|
||||
@Override
|
||||
public List<PsiMethod> findReferencedMethods(final SourcePosition position) {
|
||||
final int line = position.getLine();
|
||||
if (line < 0) {
|
||||
return Collections.emptyList(); // the document has been changed
|
||||
@@ -95,8 +53,9 @@ public class SmartStepIntoActionHandler extends DebuggerActionHandler {
|
||||
// the file is not physical
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
final Document doc = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
if (doc == null) return Collections.emptyList();
|
||||
if (line >= doc.getLineCount()) {
|
||||
return Collections.emptyList(); // the document has been changed
|
||||
}
|
||||
@@ -144,13 +103,4 @@ public class SmartStepIntoActionHandler extends DebuggerActionHandler {
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) {
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
return isPaused && hasCurrentThread;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.SourcePosition;
|
||||
import com.intellij.debugger.engine.RequestHint;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.containers.OrderedSet;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JvmSmartStepIntoActionHandler extends DebuggerActionHandler {
|
||||
public void perform(@NotNull final Project project, final AnActionEvent event) {
|
||||
final DebuggerContextImpl debuggerContext = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
doStep(project, debuggerContext.getSourcePosition(), debuggerContext.getDebuggerSession());
|
||||
}
|
||||
|
||||
private static void doStep(final @NotNull Project project, final @Nullable SourcePosition position, final @NotNull DebuggerSession session) {
|
||||
final VirtualFile file = position != null ? position.getFile().getVirtualFile() : null;
|
||||
final FileEditor fileEditor = file != null? FileEditorManager.getInstance(project).getSelectedEditor(file) : null;
|
||||
if (fileEditor instanceof TextEditor) {
|
||||
for (JvmSmartStepIntoHandler handler : Extensions.getExtensions(JvmSmartStepIntoHandler.EP_NAME)) {
|
||||
if (handler.isAvailable(position) && handler.doSmartStep(position, session, (TextEditor)fileEditor)) return;
|
||||
}
|
||||
}
|
||||
session.stepInto(true, null);
|
||||
}
|
||||
|
||||
public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) {
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
return isPaused && hasCurrentThread;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 com.intellij.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.SourcePosition;
|
||||
import com.intellij.debugger.engine.RequestHint;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: Alexander Podkhalyuzin
|
||||
* Date: 22.11.11
|
||||
*/
|
||||
public abstract class JvmSmartStepIntoHandler {
|
||||
public static ExtensionPointName<JvmSmartStepIntoHandler> EP_NAME = ExtensionPointName.create("com.intellij.debugger.jvmSmartStepIntoHandler");
|
||||
|
||||
public abstract List<PsiMethod> findReferencedMethods(SourcePosition position);
|
||||
|
||||
public abstract boolean isAvailable(SourcePosition position);
|
||||
|
||||
/**
|
||||
* Override this if you haven't PsiMethod, like in Kotlin.
|
||||
* @param position
|
||||
* @param session
|
||||
* @param fileEditor
|
||||
* @return false to continue for another handler or for default action (step into)
|
||||
*/
|
||||
public boolean doSmartStep(SourcePosition position, final DebuggerSession session, TextEditor fileEditor) {
|
||||
final List<PsiMethod> methods = findReferencedMethods(position);
|
||||
if (methods.size() > 0) {
|
||||
if (methods.size() == 1) {
|
||||
session.stepInto(true, getSmartStepFilter(methods.get(0)));
|
||||
}
|
||||
else {
|
||||
final PsiMethodListPopupStep popupStep = new PsiMethodListPopupStep(methods, new PsiMethodListPopupStep.OnChooseRunnable() {
|
||||
public void execute(PsiMethod chosenMethod) {
|
||||
session.stepInto(true, getSmartStepFilter(chosenMethod));
|
||||
}
|
||||
});
|
||||
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(popupStep);
|
||||
final RelativePoint point = DebuggerUIUtil.calcPopupLocation(((TextEditor)fileEditor).getEditor(), position.getLine());
|
||||
popup.show(point);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override in case if your JVMNames slightly different then it can be provided by getJvmSignature method.
|
||||
* @param method
|
||||
* @return SmartStepFilter
|
||||
*/
|
||||
protected RequestHint.SmartStepFilter getSmartStepFilter(PsiMethod method) {
|
||||
return new RequestHint.SmartStepFilter(method);
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class JavaDebuggerSupport extends DebuggerSupport {
|
||||
private final QuickEvaluateActionHandler myQuickEvaluateHandler = new QuickEvaluateActionHandler();
|
||||
private final JavaDebuggerSettingsPanelProvider myDebuggerSettingsPanelProvider = new JavaDebuggerSettingsPanelProvider();
|
||||
private final MuteBreakpointsActionHandler myMuteBreakpointsHandler = new MuteBreakpointsActionHandler();
|
||||
private final DebuggerActionHandler mySmartStepIntoHandler = new SmartStepIntoActionHandler();
|
||||
private final DebuggerActionHandler mySmartStepIntoHandler = new JvmSmartStepIntoActionHandler();
|
||||
private final DebuggerActionHandler myAddToWatchedActionHandler = new AddToWatchActionHandler();
|
||||
private JavaMarkObjectActionHandler myMarkObjectActionHandler = new JavaMarkObjectActionHandler();
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ public class RootsDetectionStep extends AbstractStepWithProgress<List<DetectedRo
|
||||
final Set<String> selectedTypes = new HashSet<String>();
|
||||
for (DetectedRootData rootData : myDetectedRootsChooser.getMarkedElements()) {
|
||||
for (ProjectStructureDetector detector : rootData.getSelectedDetectors()) {
|
||||
selectedTypes.add(detector.getClass().getName());
|
||||
selectedTypes.add(detector.getDetectorId());
|
||||
}
|
||||
}
|
||||
mySequence.setTypes(selectedTypes);
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ public abstract class CreateFromSourcesMode extends WizardMode {
|
||||
sequence.addCommonStep(new RootsDetectionStep(projectBuilder, context, sequence, icon, "reference.dialogs.new.project.fromCode.source"));
|
||||
for (ProjectStructureDetector detector : ProjectStructureDetector.EP_NAME.getExtensions()) {
|
||||
for (ModuleWizardStep step : detector.createWizardSteps(projectBuilder, projectBuilder.getProjectDescriptor(detector), icon)) {
|
||||
sequence.addSpecificStep(detector.getClass().getName(), step);
|
||||
sequence.addSpecificStep(detector.getDetectorId(), step);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -52,6 +52,11 @@ public abstract class JavaSourceRootDetector extends ProjectStructureDetector {
|
||||
return DirectoryProcessingResult.PROCESS_CHILDREN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetectorId() {
|
||||
return "Java";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract String getLanguageName();
|
||||
|
||||
|
||||
+4
@@ -68,6 +68,10 @@ public abstract class ProjectStructureDetector {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public String getDetectorId() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup modules and libraries for the selected roots
|
||||
*/
|
||||
|
||||
+4
-6
@@ -19,7 +19,8 @@ import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.diagnostic.errordialog.Attachment;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -105,11 +106,8 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
|
||||
String docText = context.getDocument().getText();
|
||||
DefaultInsertHandler.addImportForItem(context, item);
|
||||
if (context.getTailOffset() < 0) {
|
||||
if (ApplicationManagerEx.getApplicationEx().isInternal()) {
|
||||
LOG.error("Tail offset degraded: " + context.getStartOffset() + "; " + docText);
|
||||
} else {
|
||||
LOG.error("Tail offset degraded after insertion");
|
||||
}
|
||||
LOG.error(LogMessageEx.createEvent("Tail offset degraded after insertion", "start=" + context.getStartOffset(),
|
||||
new Attachment(context.getFile().getViewProvider().getVirtualFile().getPath(), docText)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -173,6 +173,13 @@ public class JavaCompletionUtil {
|
||||
public static boolean isInExcludedPackage(@NotNull final PsiMember member) {
|
||||
final String name = StaticImportMethodFix.getMemberQualifiedName(member);
|
||||
if (name == null) return false;
|
||||
|
||||
if (!member.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
if (member instanceof PsiMethod || member instanceof PsiField || member instanceof PsiClass && member.getContainingClass() != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CodeInsightSettings cis = CodeInsightSettings.getInstance();
|
||||
for (String excluded : cis.EXCLUDED_PACKAGES) {
|
||||
if (name.equals(excluded) || name.startsWith(excluded + ".")) {
|
||||
|
||||
@@ -987,6 +987,7 @@ public class TemplateState implements Disposable {
|
||||
for (TemplateOptionalProcessor optionalProcessor : Extensions.getExtensions(TemplateOptionalProcessor.EP_NAME)) {
|
||||
optionalProcessor.processText(myProject, myTemplate, myDocument, myTemplateRange, myEditor);
|
||||
}
|
||||
PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument);
|
||||
// for Python, we need to indent the template even if reformatting is enabled, because otherwise indents would be broken
|
||||
// and reformat wouldn't be able to fix them
|
||||
if (myTemplate.isToIndent()) {
|
||||
|
||||
@@ -41,16 +41,7 @@ class NavBarBorder implements Border {
|
||||
|
||||
g.setColor(new Color(0, 0, 0, 50));
|
||||
g.drawLine(x, y + 1, x + width, y + 1);
|
||||
} else if (NavBarRootPaneExtension.runToolbarExists()) {
|
||||
g.setColor(new Color(0, 0, 0, 50));
|
||||
g.drawLine(x, y, x + width, y);
|
||||
}
|
||||
|
||||
if (!UISettings.getInstance().SHOW_MAIN_TOOLBAR && NavBarRootPaneExtension.runToolbarExists()) {
|
||||
g.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2);
|
||||
g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Insets getBorderInsets(final Component c) {
|
||||
|
||||
+81
-13
@@ -77,7 +77,8 @@ public abstract class AbstractNavBarUI implements NavBarUI {
|
||||
@Override
|
||||
public void doPaintNavBarItem(Graphics2D g, NavBarItem item, NavBarPanel navbar) {
|
||||
final boolean floating = navbar.isInFloatingMode();
|
||||
|
||||
boolean toolbar = UISettings.getInstance().SHOW_MAIN_TOOLBAR;
|
||||
|
||||
Icon icon = item.getIcon();
|
||||
int w = item.getWidth();
|
||||
int h = item.getHeight();
|
||||
@@ -106,7 +107,7 @@ public abstract class AbstractNavBarUI implements NavBarUI {
|
||||
endShape.lineTo(w, h / 2);
|
||||
endShape.closePath();
|
||||
|
||||
if (bg != null) {
|
||||
if (bg != null && toolbar) {
|
||||
g2.setPaint(bg);
|
||||
g2.fill(shape);
|
||||
if (!item.isLastElement() || floating) {
|
||||
@@ -115,17 +116,52 @@ public abstract class AbstractNavBarUI implements NavBarUI {
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
Path2D.Double focusShape = new Path2D.Double();
|
||||
if (toolbar || floating) {
|
||||
focusShape.moveTo(w-getDecorationOffset(), 0);
|
||||
} else {
|
||||
focusShape.moveTo(0, 0);
|
||||
focusShape.lineTo(w - getDecorationOffset(), 0);
|
||||
}
|
||||
focusShape.lineTo(w - 1, h / 2);
|
||||
focusShape.lineTo(w - getDecorationOffset(), h - 1);
|
||||
if (!toolbar && !floating) {
|
||||
focusShape.lineTo(0, h - 1);
|
||||
|
||||
}
|
||||
|
||||
g2.setColor(selection);
|
||||
if (floating && item.isLastElement()) {
|
||||
g2.fillRect(0, 0, w, h);
|
||||
} else {
|
||||
g2.fill(shape);
|
||||
|
||||
g2.setColor(new Color(0, 0, 0, 70));
|
||||
g2.draw(focusShape);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.isNextSelected() && navbar.hasFocus()) {
|
||||
g2.setColor(selection);
|
||||
g2.fill(endShape);
|
||||
|
||||
Path2D.Double endFocusShape = new Path2D.Double();
|
||||
if (toolbar || floating) {
|
||||
endFocusShape.moveTo(w - getDecorationOffset(), 0);
|
||||
} else {
|
||||
endFocusShape.moveTo(w, 0);
|
||||
endFocusShape.lineTo(w - getDecorationOffset(), 0);
|
||||
}
|
||||
|
||||
endFocusShape.lineTo(w - 1, h / 2);
|
||||
endFocusShape.lineTo(w - getDecorationOffset(), h - 1);
|
||||
|
||||
if (!toolbar && !floating) {
|
||||
endFocusShape.lineTo(w, h - 1);
|
||||
}
|
||||
|
||||
g2.setColor(new Color(0, 0, 0, 70));
|
||||
g2.draw(endFocusShape);
|
||||
}
|
||||
|
||||
final int offset = item.isFirstElement() ? getFirstElementLeftOffset() : 0;
|
||||
@@ -138,20 +174,50 @@ public abstract class AbstractNavBarUI implements NavBarUI {
|
||||
int off = getDecorationOffset() - 1;
|
||||
|
||||
if (!floating || !item.isLastElement()) {
|
||||
g2.setColor(new Color(0, 0, 0, 70));
|
||||
g2.drawLine(0, 0, off, h / 2 - 1);
|
||||
g2.drawLine(off, h / 2 - 1, 0, h);
|
||||
}
|
||||
|
||||
if (!selected && !floating) {
|
||||
g2.translate(-1, 0);
|
||||
g2.setColor(new SameColor(205));
|
||||
g2.drawLine(0, 0, off, h / 2 - 1);
|
||||
g2.drawLine(off, h / 2 - 1, 0, h);
|
||||
if (toolbar || floating) {
|
||||
if (!selected && (!navbar.hasFocus() | !item.isNextSelected())) {
|
||||
drawArrow(g2, new Color(0, 0, 0, 70), new SameColor(205), off, h, !selected && !floating, false);
|
||||
}
|
||||
} else {
|
||||
if (!selected && (!navbar.hasFocus() | !item.isNextSelected())) {
|
||||
drawArrow(g2, new Color(0, 0, 0, 150), new Color(255, 255, 255, 200), off, h, !selected && !floating, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
private static void drawArrow(Graphics2D g2d, Color c, Color light, int decorationOffset, int h, boolean highlight, boolean gradient) {
|
||||
int off = decorationOffset - 1;
|
||||
|
||||
g2d.setColor(c);
|
||||
if (gradient) {
|
||||
g2d.setPaint(new GradientPaint(0, 0, new Color(c.getRed(), c.getGreen(), c.getBlue(), 10), 0, h / 2, c));
|
||||
}
|
||||
g2d.drawLine(0, 0, off, h / 2);
|
||||
|
||||
if (gradient) {
|
||||
g2d.setPaint(new GradientPaint(0, h / 2, c, 0, h, new Color(c.getRed(), c.getGreen(), c.getBlue(), 10)));
|
||||
}
|
||||
g2d.drawLine(off, h / 2, 0, h);
|
||||
|
||||
if (highlight) {
|
||||
g2d.translate(-1, 0);
|
||||
g2d.setColor(light);
|
||||
|
||||
if (gradient) {
|
||||
g2d.setPaint(new GradientPaint(0, 0, new Color(light.getRed(), light.getGreen(), light.getBlue(), 10), 0, h / 2, light));
|
||||
}
|
||||
g2d.drawLine(0, 0, off, h / 2);
|
||||
|
||||
|
||||
if (gradient) {
|
||||
g2d.setPaint(new GradientPaint(0, h / 2, light, 0, h, new Color(light.getRed(), light.getGreen(), light.getBlue(), 10)));
|
||||
}
|
||||
g2d.drawLine(off, h / 2, 0, h);
|
||||
}
|
||||
}
|
||||
|
||||
private int getDecorationOffset() {
|
||||
return 8;
|
||||
@@ -187,6 +253,8 @@ public abstract class AbstractNavBarUI implements NavBarUI {
|
||||
@Override
|
||||
public void doPaintNavBarPanel(Graphics2D g, Rectangle r, boolean mainToolbarVisible, boolean undocked) {
|
||||
g.setColor(getBackgroundColor());
|
||||
g.fillRect(0, 0, r.width, r.height);
|
||||
if (mainToolbarVisible) {
|
||||
g.fillRect(0, 0, r.width, r.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -1178,8 +1178,14 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
setOpaque(false);
|
||||
} else {
|
||||
if (isInsideNavBar()) {
|
||||
setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2));
|
||||
}
|
||||
else {
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
|
||||
}
|
||||
|
||||
setMinimumButtonSize(DEFAULT_MINIMUM_BUTTON_SIZE);
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
|
||||
setOpaque(true);
|
||||
setLayoutPolicy(AUTO_LAYOUT_POLICY);
|
||||
}
|
||||
|
||||
+7
-3
@@ -42,7 +42,6 @@ import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import com.intellij.ui.tabs.JBTabs;
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.PairFunction;
|
||||
@@ -148,14 +147,19 @@ public class EditorsSplitters extends JPanel {
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
|
||||
if (myCurrentWindow == null || myCurrentWindow.getFiles().length == 0) {
|
||||
g.setColor(new Color(0, 0, 0, 50));
|
||||
g.drawLine(0, 0, getWidth(), 0);
|
||||
}
|
||||
|
||||
if (showEmptyText()) {
|
||||
final boolean darkerColors = UIUtil.isUnderAquaLookAndFeel() || UIUtil.isUnderGTKLookAndFeel();
|
||||
UIUtil.applyRenderingHints(g);
|
||||
g.setColor(darkerColors ? Gray._100 : Color.LIGHT_GRAY);
|
||||
g.setColor(darkerColors ? Gray._100 : Color.DARK_GRAY);
|
||||
g.setFont(UIUtil.getLabelFont().deriveFont(18f));
|
||||
|
||||
final UIUtil.TextPainter painter = new UIUtil.TextPainter(1.4f);
|
||||
painter.appendLine("No files are open").underlined(darkerColors ? Gray._150 : Color.LIGHT_GRAY)
|
||||
painter.appendLine("No files are open").underlined(darkerColors ? Gray._150 : Color.DARK_GRAY)
|
||||
.appendLine("Open Project View with " + KeymapUtil.getShortcutText(new KeyboardShortcut(
|
||||
KeyStroke.getKeyStroke((SystemInfo.isMac ? "meta" : "alt") + " 1"), null))).smaller().withBullet()
|
||||
.appendLine("Open Recent files with " + getActionShortcutText("RecentFiles")).smaller().withBullet()
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.repo;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitBranchTrackInfo {
|
||||
|
||||
private final String myBranch;
|
||||
private final GitRemote myRemote;
|
||||
private final String myRemoteBranch;
|
||||
private final boolean myMerge;
|
||||
|
||||
GitBranchTrackInfo(@NotNull String branch, @NotNull GitRemote remote, @NotNull String remoteBranch, boolean merge) {
|
||||
myBranch = branch;
|
||||
myMerge = merge;
|
||||
myRemoteBranch = remoteBranch;
|
||||
myRemote = remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s %s %b", myBranch, myRemote, myRemoteBranch, myMerge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GitBranchTrackInfo that = (GitBranchTrackInfo)o;
|
||||
|
||||
if (myMerge != that.myMerge) return false;
|
||||
if (myBranch != null ? !myBranch.equals(that.myBranch) : that.myBranch != null) return false;
|
||||
if (myRemote != null ? !myRemote.equals(that.myRemote) : that.myRemote != null) return false;
|
||||
if (myRemoteBranch != null ? !myRemoteBranch.equals(that.myRemoteBranch) : that.myRemoteBranch != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myBranch != null ? myBranch.hashCode() : 0;
|
||||
result = 31 * result + (myRemote != null ? myRemote.hashCode() : 0);
|
||||
result = 31 * result + (myRemoteBranch != null ? myRemoteBranch.hashCode() : 0);
|
||||
result = 31 * result + (myMerge ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package git4idea.repo;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.ini4j.Ini;
|
||||
import org.ini4j.Profile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -52,11 +53,14 @@ class GitConfig {
|
||||
|
||||
private static final Pattern REMOTE_SECTION = Pattern.compile("remote \"(.*)\"");
|
||||
private static final Pattern URL_SECTION = Pattern.compile("url \"(.*)\"");
|
||||
private static final Pattern BRANCH_SECTION = Pattern.compile("branch \"(.*)\"");
|
||||
|
||||
private final Collection<GitRemote> myRemotes;
|
||||
private final Collection<GitBranchTrackInfo> myBranchTrackInfos;
|
||||
|
||||
private GitConfig(Collection<GitRemote> remotes) {
|
||||
private GitConfig(Collection<GitRemote> remotes, @NotNull Collection<GitBranchTrackInfo> branchTrackInfos) {
|
||||
myRemotes = remotes;
|
||||
myBranchTrackInfos = branchTrackInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,10 +79,19 @@ class GitConfig {
|
||||
* </p>
|
||||
* @return Git remotes defined in {@code .git/config}.
|
||||
*/
|
||||
@NotNull
|
||||
Collection<GitRemote> getRemotes() {
|
||||
return myRemotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return branch tracking information defined in {@code .git/config}.
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<GitBranchTrackInfo> getBranchTrackInfos() {
|
||||
return myBranchTrackInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of GitConfig by reading information from the specified {@code .git/config} file.
|
||||
* @param configFile
|
||||
@@ -102,6 +115,76 @@ class GitConfig {
|
||||
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginManager.getPluginByClassName(GitConfig.class.getName()));
|
||||
ClassLoader classLoader = plugin == null ? null : plugin.getPluginClassLoader(); // null if IDEA is started from IDEA
|
||||
|
||||
Collection<GitRemote> gitRemotes = parseRemotes(ini, classLoader);
|
||||
Collection<GitBranchTrackInfo> trackedInfos = parseTrackedInfos(ini, classLoader, gitRemotes);
|
||||
|
||||
return new GitConfig(gitRemotes, trackedInfos);
|
||||
}
|
||||
|
||||
private static Collection<GitBranchTrackInfo> parseTrackedInfos(Ini ini, ClassLoader classLoader, Collection<GitRemote> remotes) {
|
||||
Collection<GitBranchTrackInfo> branchTrackInfos = new ArrayList<GitBranchTrackInfo>();
|
||||
for (Map.Entry<String, Profile.Section> stringSectionEntry : ini.entrySet()) {
|
||||
String sectionName = stringSectionEntry.getKey();
|
||||
Profile.Section section = stringSectionEntry.getValue();
|
||||
if (sectionName.startsWith("branch")) {
|
||||
BranchConfig branchConfig = parseBranchSection(sectionName, section, classLoader);
|
||||
GitBranchTrackInfo branchTrackInfo = convertBranchConfig(branchConfig, remotes);
|
||||
if (branchTrackInfo != null) {
|
||||
branchTrackInfos.add(branchTrackInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return branchTrackInfos;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GitBranchTrackInfo convertBranchConfig(@Nullable BranchConfig branchConfig, @NotNull Collection<GitRemote> remotes) {
|
||||
if (branchConfig == null) {
|
||||
return null;
|
||||
}
|
||||
String branchName = branchConfig.getName();
|
||||
String remoteName = branchConfig.getBean().getRemote();
|
||||
String mergeName = branchConfig.getBean().getMerge();
|
||||
String rebaseName = branchConfig.getBean().getRebase();
|
||||
|
||||
if (StringUtil.isEmptyOrSpaces(mergeName) && StringUtil.isEmptyOrSpaces(rebaseName)) {
|
||||
LOG.info("No branch." + branchName + ".merge/rebase item in the .git/config");
|
||||
return null;
|
||||
}
|
||||
if (StringUtil.isEmptyOrSpaces(remoteName)) {
|
||||
LOG.info("No branch." + branchName + ".remote item in the .git/config");
|
||||
return null;
|
||||
}
|
||||
boolean merge = mergeName != null;
|
||||
String remoteBranch = (merge ? mergeName : rebaseName);
|
||||
|
||||
GitRemote branchRemote = null;
|
||||
for (GitRemote remote : remotes) {
|
||||
if (remote.getName().equals(remoteName)) {
|
||||
branchRemote = remote;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (branchRemote == null) {
|
||||
LOG.info("No remote found with name " + remoteName);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new GitBranchTrackInfo(branchName, branchRemote, remoteBranch, merge);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BranchConfig parseBranchSection(String sectionName, Profile.Section section, ClassLoader classLoader) {
|
||||
BranchBean branchBean = section.as(BranchBean.class, classLoader);
|
||||
Matcher matcher = BRANCH_SECTION.matcher(sectionName);
|
||||
if (matcher.matches()) {
|
||||
return new BranchConfig(matcher.group(1), branchBean);
|
||||
}
|
||||
LOG.error(String.format("Invalid branch section format in .git/config. sectionName: %s section: %s", sectionName, section));
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Collection<GitRemote> parseRemotes(Ini ini, ClassLoader classLoader) {
|
||||
Collection<Remote> remotes = new ArrayList<Remote>();
|
||||
Collection<Url> urls = new ArrayList<Url>();
|
||||
for (Map.Entry<String, Profile.Section> stringSectionEntry : ini.entrySet()) {
|
||||
@@ -122,9 +205,7 @@ class GitConfig {
|
||||
}
|
||||
}
|
||||
|
||||
Collection<GitRemote> gitRemotes = makeGitRemotes(remotes, urls);
|
||||
return new GitConfig(gitRemotes);
|
||||
|
||||
return makeGitRemotes(remotes, urls);
|
||||
}
|
||||
|
||||
// populate GitRemotes with substituting urls when needed
|
||||
@@ -345,6 +426,30 @@ class GitConfig {
|
||||
@Nullable String getInsteadOf();
|
||||
@Nullable String getPushInsteadOf();
|
||||
}
|
||||
|
||||
private static class BranchConfig {
|
||||
private final String myName;
|
||||
private final BranchBean myBean;
|
||||
|
||||
public BranchConfig(String name, BranchBean bean) {
|
||||
myName = name;
|
||||
myBean = bean;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public BranchBean getBean() {
|
||||
return myBean;
|
||||
}
|
||||
}
|
||||
|
||||
private interface BranchBean {
|
||||
@Nullable String getRemote();
|
||||
@Nullable String getMerge();
|
||||
@Nullable String getRebase();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String notNull(@Nullable String s) {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
@@ -0,0 +1 @@
|
||||
b0 No branches
|
||||
@@ -0,0 +1,14 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
[remote "origin"]
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
url = /Users/loki/temp/parent.git
|
||||
[branch "unexistant_remote"]
|
||||
remote = unexistant
|
||||
merge = refs/heads/master
|
||||
[branch "no_merge_item"]
|
||||
remote = origin
|
||||
@@ -0,0 +1,2 @@
|
||||
b1 No valid branches
|
||||
One with incorrect remote, other without merge/rebase item
|
||||
@@ -0,0 +1,12 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
[remote "origin"]
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
url = git@git.labs.intellij.net:idea/community
|
||||
[branch "master"]
|
||||
remote = origin
|
||||
merge = refs/heads/master
|
||||
@@ -0,0 +1 @@
|
||||
b2 One branch
|
||||
@@ -0,0 +1,6 @@
|
||||
BRANCH
|
||||
master
|
||||
origin git@git.labs.intellij.net:idea/community git@git.labs.intellij.net:idea/community +refs/heads/*:refs/remotes/origin/* +refs/heads/*:refs/remotes/origin/*
|
||||
refs/heads/master
|
||||
origin/master
|
||||
merge
|
||||
@@ -0,0 +1,20 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
|
||||
[remote "origin"]
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
url = git@git.labs.intellij.net:idea/community
|
||||
[remote "github"]
|
||||
fetch = +refs/heads/*:refs/remotes/github/*
|
||||
url = https://github.com/JetBrains/intellij-community.git
|
||||
|
||||
[branch "master"]
|
||||
remote = origin
|
||||
merge = refs/heads/master
|
||||
[branch "github_feature"]
|
||||
remote = github
|
||||
rebase = refs/heads/feature
|
||||
@@ -0,0 +1,2 @@
|
||||
b3 Two different branches
|
||||
Two valid branches with 2 remotes. One merge, second rebase.
|
||||
@@ -0,0 +1,12 @@
|
||||
BRANCH
|
||||
master
|
||||
origin git@git.labs.intellij.net:idea/community git@git.labs.intellij.net:idea/community +refs/heads/*:refs/remotes/origin/* +refs/heads/*:refs/remotes/origin/*
|
||||
refs/heads/master
|
||||
origin/master
|
||||
merge
|
||||
BRANCH
|
||||
github_feature
|
||||
github https://github.com/JetBrains/intellij-community.git https://github.com/JetBrains/intellij-community.git +refs/heads/*:refs/remotes/github/* +refs/heads/*:refs/remotes/github/*
|
||||
refs/heads/feature
|
||||
github/feature
|
||||
rebase
|
||||
@@ -0,0 +1,13 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
[remote "origin"]
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
url = git@git.labs.intellij.net:idea/community
|
||||
[branch "master"]
|
||||
remote = origin
|
||||
merge = refs/heads/master
|
||||
rebase = refs/heads/master
|
||||
@@ -0,0 +1,2 @@
|
||||
b4 Branch with both merge and rebase
|
||||
Then only merge is taken into consideration.
|
||||
@@ -0,0 +1,6 @@
|
||||
BRANCH
|
||||
master
|
||||
origin git@git.labs.intellij.net:idea/community git@git.labs.intellij.net:idea/community +refs/heads/*:refs/remotes/origin/* +refs/heads/*:refs/remotes/origin/*
|
||||
refs/heads/master
|
||||
origin/master
|
||||
merge
|
||||
@@ -23,6 +23,7 @@ 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.*;
|
||||
|
||||
@@ -33,11 +34,25 @@ import static org.testng.Assert.assertNotNull;
|
||||
*/
|
||||
public class GitConfigTest {
|
||||
|
||||
@DataProvider(name = "provider")
|
||||
public Object[][] loadData() throws IOException {
|
||||
@DataProvider(name = "remote")
|
||||
public Object[][] loadRemotes() throws IOException {
|
||||
return loadData("remote");
|
||||
}
|
||||
|
||||
@DataProvider(name = "branch")
|
||||
public Object[][] loadBranches() throws IOException {
|
||||
return loadData("branch");
|
||||
}
|
||||
|
||||
public static Object[][] loadData(String subfolder) throws IOException {
|
||||
File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea"));
|
||||
File dataDir = new File(new File(pluginRoot, "testData"), "config");
|
||||
File[] tests = dataDir.listFiles();
|
||||
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];
|
||||
@@ -67,13 +82,44 @@ public class GitConfigTest {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void test(String testName, File configFile, File resultFile) throws IOException {
|
||||
@Test(dataProvider = "remote")
|
||||
public void testRemotes(String testName, File configFile, File resultFile) throws IOException {
|
||||
GitConfig config = GitConfig.read(configFile);
|
||||
GitTestUtil.assertEqualCollections(config.getRemotes(), readResults(resultFile));
|
||||
GitTestUtil.assertEqualCollections(config.getRemotes(), readRemoteResults(resultFile));
|
||||
}
|
||||
|
||||
private static Set<GitRemote> readResults(File resultFile) throws IOException {
|
||||
@Test(dataProvider = "branch")
|
||||
public void testBranches(String testName, File configFile, File resultFile) throws IOException {
|
||||
GitConfig config = GitConfig.read(configFile);
|
||||
GitTestUtil.assertEqualCollections(config.getBranchTrackInfos(), readBranchResults(resultFile));
|
||||
}
|
||||
|
||||
private static Collection<GitBranchTrackInfo> readBranchResults(File file) throws IOException {
|
||||
String content = FileUtil.loadFile(file);
|
||||
Collection<GitBranchTrackInfo> remotes = new ArrayList<GitBranchTrackInfo>();
|
||||
String[] remStrings = content.split("BRANCH\n");
|
||||
for (String remString : remStrings) {
|
||||
if (StringUtil.isEmptyOrSpaces(remString)) {
|
||||
continue;
|
||||
}
|
||||
String[] info = remString.split("\n");
|
||||
String branch = info[0];
|
||||
GitRemote remote = getRemote(info[1]);
|
||||
String remoteSpec = info[2];
|
||||
String remoteBranchName = info[3];
|
||||
boolean merge = info[4].equals("merge");
|
||||
remotes.add(new GitBranchTrackInfo(branch, remote, remoteSpec, merge));
|
||||
}
|
||||
return remotes;
|
||||
}
|
||||
|
||||
private static GitRemote getRemote(String remoteString) {
|
||||
String[] remoteInfo = remoteString.split(" ");
|
||||
return new GitRemote(getOrEmpty(remoteInfo, 0), Collections.singletonList(getOrEmpty(remoteInfo, 1)),
|
||||
Collections.singletonList(getOrEmpty(remoteInfo, 2)), getOrEmpty(remoteInfo, 3), getOrEmpty(remoteInfo, 4));
|
||||
}
|
||||
|
||||
private static Set<GitRemote> readRemoteResults(File resultFile) throws IOException {
|
||||
String content = FileUtil.loadFile(resultFile);
|
||||
Set<GitRemote> remotes = new HashSet<GitRemote>();
|
||||
String[] remStrings = content.split("REMOTE\n");
|
||||
|
||||
@@ -15,10 +15,17 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy;
|
||||
|
||||
import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil;
|
||||
import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetector;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -41,9 +48,47 @@ public class GroovySourceRootDetector extends JavaSourceRootDetector {
|
||||
return new NullableFunction<CharSequence, String>() {
|
||||
@Override
|
||||
public String fun(CharSequence charSequence) {
|
||||
//todo[nik] implement groovy-specific package name parsing?
|
||||
return JavaSourceRootDetectionUtil.getPackageName(charSequence);
|
||||
return getPackageName(charSequence);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getPackageName(CharSequence text) {
|
||||
Lexer lexer = new GroovyLexer();
|
||||
lexer.start(text);
|
||||
skipWhitespacesAndComments(lexer);
|
||||
final IElementType firstToken = lexer.getTokenType();
|
||||
if (firstToken != GroovyTokenTypes.kPACKAGE) {
|
||||
return "";
|
||||
}
|
||||
lexer.advance();
|
||||
skipWhitespacesAndComments(lexer);
|
||||
|
||||
final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
while(true){
|
||||
if (lexer.getTokenType() != GroovyTokenTypes.mIDENT) break;
|
||||
buffer.append(text, lexer.getTokenStart(), lexer.getTokenEnd());
|
||||
lexer.advance();
|
||||
skipWhitespacesAndComments(lexer);
|
||||
if (lexer.getTokenType() != GroovyTokenTypes.mDOT) break;
|
||||
buffer.append('.');
|
||||
lexer.advance();
|
||||
skipWhitespacesAndComments(lexer);
|
||||
}
|
||||
String packageName = buffer.toString();
|
||||
if (packageName.length() == 0 || StringUtil.endsWithChar(packageName, '.')) return null;
|
||||
return packageName;
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void skipWhitespacesAndComments(Lexer lexer) {
|
||||
while(TokenSets.ALL_COMMENT_TOKENS.contains(lexer.getTokenType()) || TokenSets.WHITE_SPACES_SET.contains(lexer.getTokenType())) {
|
||||
lexer.advance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.ide
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.plugins.groovy.GroovySourceRootDetector
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class GroovySourceRootDetectorTest extends TestCase {
|
||||
public void testEmpty() {
|
||||
doTest("", "")
|
||||
}
|
||||
|
||||
public void testComment() {
|
||||
doTest("//comment", "")
|
||||
doTest(" /* comment */", "")
|
||||
}
|
||||
|
||||
public void testStatement() {
|
||||
doTest("def a = 0;", "")
|
||||
}
|
||||
|
||||
public void testSimplePackage() {
|
||||
doTest("package simple", "simple")
|
||||
doTest("package simple;", "simple")
|
||||
doTest("""//comment
|
||||
package simple;""", "simple")
|
||||
}
|
||||
|
||||
public void testComplexPackage() {
|
||||
doTest("package com.simple", "com.simple")
|
||||
doTest("package com.simple;", "com.simple")
|
||||
doTest("""
|
||||
package com.simple;""", "com.simple")
|
||||
doTest("""/**
|
||||
@author nik;
|
||||
*/
|
||||
package com.simple;""", "com.simple")
|
||||
}
|
||||
|
||||
|
||||
def doTest(String text, String expectedPackageName) {
|
||||
assertEquals(expectedPackageName, GroovySourceRootDetector.getPackageName(text))
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,8 @@
|
||||
<extensionPoint name="debugger.positionManagerFactory"
|
||||
interface="com.intellij.debugger.PositionManagerFactory"
|
||||
area="IDEA_PROJECT"/>
|
||||
<extensionPoint name="debugger.jvmSmartStepIntoHandler"
|
||||
interface="com.intellij.debugger.actions.JvmSmartStepIntoHandler"/>
|
||||
|
||||
<extensionPoint name="allOverridingMethodsSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
<extensionPoint name="annotatedElementsSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
@@ -1160,6 +1162,7 @@
|
||||
<debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.AnyExceptionBreakpointFactory"/>
|
||||
<debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.FieldBreakpointFactory"/>
|
||||
<debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.MethodBreakpointFactory"/>
|
||||
<debugger.jvmSmartStepIntoHandler implementation="com.intellij.debugger.actions.JavaSmartStepIntoHandler"/>
|
||||
|
||||
<dom.uiControlsProvider implementation="com.intellij.util.xml.impl.JavaDomApplicationComponent"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user