From 190a395ee10b898e1ba1f0e80d6c8498f01ac570 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 19 Aug 2013 14:21:32 +0200 Subject: [PATCH 01/13] fix fill color and opaque --- .../wm/impl/status/ToolWindowWidgetInfoPanel.form | 9 +++++++-- .../openapi/wm/impl/status/ToolWindowsWidget.java | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowWidgetInfoPanel.form b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowWidgetInfoPanel.form index 780cda9112f1..bb9756e72a82 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowWidgetInfoPanel.form +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowWidgetInfoPanel.form @@ -5,7 +5,9 @@ - + + + @@ -45,7 +47,9 @@ - + + + @@ -54,6 +58,7 @@ + diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java index 04138d7a4c56..fbc593eaee3b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java @@ -184,7 +184,7 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB public void addNotify() { super.addNotify(); final String key = "toolwindow.stripes.buttons.info.shown"; - if (UISettings.getInstance().HIDE_TOOL_STRIPES && !PropertiesComponent.getInstance().isTrueValue(key)) { + if (true || UISettings.getInstance().HIDE_TOOL_STRIPES && !PropertiesComponent.getInstance().isTrueValue(key)) { final Alarm alarm = new Alarm(); alarm.addRequest(new Runnable() { @Override @@ -316,9 +316,9 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB GraphicsUtil.setupAAPainting(g); ((Graphics2D)g).setPaint(new GradientPaint(0, 0, new JBColor(new Color(77, 143, 253), new Color(52, 74, 100)), 0, getHeight(), new JBColor(new Color(71, 135, 237), new Color(38, 53, 73)))); - g.fillRoundRect(0,0,getWidth(), getHeight(), 5,5); + g.fillRoundRect(0,0,getWidth()-1, getHeight()-1, 5,5); g.setColor(new JBColor(new Color(48, 121, 237), new Color(87, 93, 101))); - g.drawRoundRect(0,0,getWidth(), getHeight(), 5,5); + g.drawRoundRect(0,0,getWidth()-1, getHeight()-1, 5,5); } }; } From bdbe4421c6103293b3a8e62fee4967a3978c2b46 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 19 Aug 2013 14:26:52 +0200 Subject: [PATCH 02/13] pushed by mistake --- .../com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java index fbc593eaee3b..c3b21e85047f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java @@ -184,7 +184,7 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB public void addNotify() { super.addNotify(); final String key = "toolwindow.stripes.buttons.info.shown"; - if (true || UISettings.getInstance().HIDE_TOOL_STRIPES && !PropertiesComponent.getInstance().isTrueValue(key)) { + if (UISettings.getInstance().HIDE_TOOL_STRIPES && !PropertiesComponent.getInstance().isTrueValue(key)) { final Alarm alarm = new Alarm(); alarm.addRequest(new Runnable() { @Override From a0b13bedd5182d5fa5c3f8fac326e8f758326e4c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 19 Aug 2013 14:37:17 +0200 Subject: [PATCH 03/13] add "new in 13" and some missing info to description --- .../src/inspectionDescriptions/BooleanParameter.html | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html b/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html index bb138c1a4ca8..5653cdab465c 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html @@ -1,10 +1,14 @@ -It's almost always a mistake to add a boolean parameter to a public method (part of an API). When reading code using such a method -it can be difficult to decipher what the boolean stands for without looking at the source or documentation. This is also known as -the boolean trap. The boolean parameter can often -be profitably replaced with an enum +It's almost always a mistake to add a boolean parameter to a public method (part of an API) if that method is not a setter. +When reading code using such a method, it can be difficult to decipher what the boolean stands for without looking at +the source or documentation. +This problem is also known as the boolean trap. +The boolean parameter can often be profitably replaced with an enum +

Use the option below to only warn when a method contains more than one boolean parameter. +

+New in 13 \ No newline at end of file From acd9ec720e78584f8c478d21bd756304b57a4546 Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 19 Aug 2013 16:39:52 +0400 Subject: [PATCH 04/13] added manifest module to runtime classpath for tests --- resources/resources.iml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/resources.iml b/resources/resources.iml index 1f8b3f27d2df..8299c81e550a 100644 --- a/resources/resources.iml +++ b/resources/resources.iml @@ -12,6 +12,7 @@ + From 1fa6eba515f1d7e4a020d35e0fc78b9170fb27ec Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 19 Aug 2013 16:48:21 +0400 Subject: [PATCH 05/13] IDEA-86299 Support for geb - add completion/resolving for members of TestNG tests --- plugins/groovy/src/META-INF/plugin.xml | 1 + .../geb/GebTestNGTestMemberContributor.java | 45 ++++++++++++++++++ .../plugins/groovy/geb/GebTestsTest.groovy | 12 +++++ .../testdata/mockGeb/geb-testng-0.7.2.jar | Bin 0 -> 8010 bytes 4 files changed, 58 insertions(+) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.java create mode 100644 plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 2a1d2767e6e9..a07501b10569 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -97,6 +97,7 @@ + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.java new file mode 100644 index 000000000000..627197ea3fdb --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2013 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.geb; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import com.intellij.psi.ResolveState; +import com.intellij.psi.scope.PsiScopeProcessor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor; + +/** + * @author zolotov + */ +public class GebTestNGTestMemberContributor extends NonCodeMembersContributor { + + @Override + protected String getParentClassName() { + return "geb.testng.GebTest"; + } + + @Override + public void processDynamicElements(@NotNull PsiType qualifierType, + PsiClass aClass, + PsiScopeProcessor processor, + PsiElement place, + ResolveState state) { + GebUtil.contributeMembersInsideTest(processor, place, state); + } + +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy index c733fcf74295..81008c72449b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy @@ -43,6 +43,18 @@ class FooTest extends geb.junit4.GebReportingTest { } } +""") + + TestUtils.checkCompletionContains(myFixture, "\$()", "to()", "go()", "currentWindow", "verifyAt()", "title") + } + + void testTestNGTestMemberCompletion() { + myFixture.configureByText("FooTest.groovy", """ +class FooTest extends geb.testng.GebReportingTest { + def testFoo() { + + } +} """) TestUtils.checkCompletionContains(myFixture, "\$()", "to()", "go()", "currentWindow", "verifyAt()", "title") diff --git a/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar b/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..c61f665bb38cdbf3dfc1cfb1c225eae6d976c758 GIT binary patch literal 8010 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 literal 0 HcmV?d00001 From f27aee3e4ac834e94391609d554f0ad0d39e836b Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Aug 2013 11:28:04 +0400 Subject: [PATCH 06/13] Github: change Task settings layout --- .../github/tasks/GithubRepositoryEditor.java | 90 +++++++++++++------ 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java index fe6344986db8..5d6d8e5e0aeb 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java @@ -1,16 +1,16 @@ package org.jetbrains.plugins.github.tasks; import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.config.BaseRepositoryEditor; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBTextField; import com.intellij.util.Consumer; import com.intellij.util.ThrowableConvertor; import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.GridBag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.github.util.GithubAuthData; @@ -31,25 +31,29 @@ import java.io.IOException; * @author Dennis.Ushakov */ public class GithubRepositoryEditor extends BaseRepositoryEditor { - private JTextField myToken; - private JTextField myRepoName; - private JTextField myRepoAuthor; + private MyTextField myHost; + private MyTextField myRepoAuthor; + private MyTextField myRepoName; + private MyTextField myToken; private JButton myTokenButton; - private JBLabel myRepoAuthorLabel; - private JBLabel myRepoLabel; + private JBLabel myHostLabel; + private JBLabel myRepositoryLabel; private JBLabel myTokenLabel; public GithubRepositoryEditor(final Project project, final GithubRepository repository, Consumer changeListener) { super(project, repository, changeListener); - myUserNameText.setVisible(false); + myUrlLabel.setVisible(false); + myURLText.setVisible(false); myUsernameLabel.setVisible(false); - myPasswordText.setVisible(false); + myUserNameText.setVisible(false); myPasswordLabel.setVisible(false); + myPasswordText.setVisible(false); myUseHttpAuthenticationCheckBox.setVisible(false); - myToken.setText(repository.getToken()); + myHost.setText(repository.getUrl()); myRepoAuthor.setText(repository.getRepoAuthor()); myRepoName.setText(repository.getRepoName()); + myToken.setText(repository.getToken()); DocumentListener buttonUpdater = new DocumentAdapter() { @Override @@ -58,29 +62,32 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor Date: Mon, 19 Aug 2013 13:58:47 +0400 Subject: [PATCH 07/13] Github: fix parameters order --- .../jetbrains/plugins/github/ui/GithubSettingsPanel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java index b1f08bcaf93f..1ba076e123b0 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java @@ -84,18 +84,18 @@ public class GithubSettingsPanel { try { GithubUser user = GithubUtil.checkAuthData(getAuthData()); if (GithubAuthData.AuthType.TOKEN.equals(getAuthType())) { - GithubNotifications.showInfoDialog(myPane, "Connection successful for user " + user.getLogin(), "Success"); + GithubNotifications.showInfoDialog(myPane, "Success", "Connection successful for user " + user.getLogin()); } else { - GithubNotifications.showInfoDialog(myPane, "Connection successful", "Success"); + GithubNotifications.showInfoDialog(myPane, "Success", "Connection successful"); } } catch (GithubAuthenticationException ex) { - GithubNotifications.showErrorDialog(myPane, "Can't login using given credentials: " + ex.getMessage(), "Login Failure"); + GithubNotifications.showErrorDialog(myPane, "Login Failure", "Can't login using given credentials: " + ex.getMessage()); } catch (IOException ex) { LOG.info(ex); - GithubNotifications.showErrorDialog(myPane, "Can't login: " + GithubUtil.getErrorTextFromException(ex), "Login Failure"); + GithubNotifications.showErrorDialog(myPane, "Login Failure", "Can't login: " + GithubUtil.getErrorTextFromException(ex)); } } }); From e690fc0bf902a81ee2d84f19901b058e91ff8d70 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Aug 2013 14:38:44 +0400 Subject: [PATCH 08/13] Github: change settings layout --- .../github/ui/GithubSettingsPanel.form | 145 +++++++++++++----- .../github/ui/GithubSettingsPanel.java | 20 ++- 2 files changed, 120 insertions(+), 45 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form index c0d2af8512d8..b540bd9c3ea5 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form @@ -1,6 +1,6 @@

- + @@ -8,25 +8,9 @@ - - - - - - - - - - - - - - - - - + @@ -39,38 +23,23 @@ - - - - - - - - - - - - - - - - - + - + + - + @@ -78,10 +47,110 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java index 1ba076e123b0..365fa2f36b2b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.HyperlinkAdapter; +import com.intellij.ui.components.JBLabel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.github.util.GithubAuthData; @@ -35,6 +36,8 @@ import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.HyperlinkEvent; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; import java.awt.*; import java.awt.event.*; import java.io.IOException; @@ -54,12 +57,13 @@ public class GithubSettingsPanel { private JTextField myLoginTextField; private JPasswordField myPasswordField; + private JPasswordField myTokenField; private JTextPane mySignupTextField; private JPanel myPane; private JButton myTestButton; private JTextField myHostTextField; private ComboBox myAuthTypeComboBox; - private JLabel myLoginLabel; + private JPanel myCardPanel; private boolean myCredentialsModified; @@ -137,14 +141,11 @@ public class GithubSettingsPanel { if (e.getStateChange() == ItemEvent.SELECTED) { String item = e.getItem().toString(); if (AUTH_PASSWORD.equals(item)) { - myLoginLabel.setVisible(true); - myLoginTextField.setVisible(true); + ((CardLayout)myCardPanel.getLayout()).show(myCardPanel, AUTH_PASSWORD); } else if (AUTH_TOKEN.equals(item)) { - myLoginLabel.setVisible(false); - myLoginTextField.setVisible(false); + ((CardLayout)myCardPanel.getLayout()).show(myCardPanel, AUTH_TOKEN); } - myPane.validate(); erasePassword(); } } @@ -240,5 +241,10 @@ public class GithubSettingsPanel { public void resetCredentialsModification() { myCredentialsModified = false; } -} + private void createUIComponents() { + Document doc = new PlainDocument(); + myPasswordField = new JPasswordField(doc, null, 0); + myTokenField = new JPasswordField(doc, null, 0); + } +} From 407b034785de1e82d49aef0488e0d92d0499096a Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Aug 2013 15:40:08 +0400 Subject: [PATCH 09/13] Github: add ability to disable proxy --- .../plugins/github/api/GithubApiUtil.java | 6 +++--- .../github/tasks/GithubRepository.java | 2 +- .../plugins/github/util/GithubAuthData.java | 20 +++++++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java index ba7a8cdbea8d..2f634d08b939 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java @@ -135,7 +135,7 @@ public class GithubApiUtil { @Nullable final String requestBody, @NotNull final Collection
headers, @NotNull final HttpVerb verb) throws IOException { - HttpClient client = getHttpClient(auth.getBasicAuth()); + HttpClient client = getHttpClient(auth.getBasicAuth(), auth.isUseProxy()); return GithubSslSupport.getInstance() .executeSelfSignedCertificateAwareRequest(client, uri, new ThrowableConvertor() { @Override @@ -173,7 +173,7 @@ public class GithubApiUtil { } @NotNull - private static HttpClient getHttpClient(@Nullable GithubAuthData.BasicAuth basicAuth) { + private static HttpClient getHttpClient(@Nullable GithubAuthData.BasicAuth basicAuth, boolean useProxy) { final HttpClient client = new HttpClient(); HttpConnectionManagerParams params = client.getHttpConnectionManager().getParams(); params.setConnectionTimeout(CONNECTION_TIMEOUT); //set connection timeout (how long it takes to connect to remote host) @@ -182,7 +182,7 @@ public class GithubApiUtil { client.getParams().setContentCharset("UTF-8"); // Configure proxySettings if it is required final HttpConfigurable proxySettings = HttpConfigurable.getInstance(); - if (proxySettings.USE_HTTP_PROXY && !StringUtil.isEmptyOrSpaces(proxySettings.PROXY_HOST)) { + if (useProxy && proxySettings.USE_HTTP_PROXY && !StringUtil.isEmptyOrSpaces(proxySettings.PROXY_HOST)) { client.getHostConfiguration().setProxy(proxySettings.PROXY_HOST, proxySettings.PROXY_PORT); if (proxySettings.PROXY_AUTHENTICATION) { client.getState().setProxyCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxySettings.PROXY_LOGIN, diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java index 4f4626680673..3d337c289c56 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java @@ -269,7 +269,7 @@ public class GithubRepository extends BaseRepositoryImpl { } private GithubAuthData getAuthData() { - return GithubAuthData.createTokenAuth(getUrl(), getToken()); + return GithubAuthData.createTokenAuth(getUrl(), getToken(), isUseProxy()); } @Override diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java index 5de9a65b6de9..63e93a6e230e 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java +++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java @@ -36,15 +36,19 @@ public class GithubAuthData { @NotNull private final String myHost; @Nullable private final BasicAuth myBasicAuth; @Nullable private final TokenAuth myTokenAuth; + private final boolean myUseProxy; + private GithubAuthData(@NotNull AuthType authType, @NotNull String host, @Nullable BasicAuth basicAuth, - @Nullable TokenAuth tokenAuth) { + @Nullable TokenAuth tokenAuth, + boolean useProxy) { myAuthType = authType; myHost = host; myBasicAuth = basicAuth; myTokenAuth = tokenAuth; + myUseProxy = useProxy; } public static GithubAuthData createAnonymous() { @@ -52,15 +56,19 @@ public class GithubAuthData { } public static GithubAuthData createAnonymous(@NotNull String host) { - return new GithubAuthData(AuthType.ANONYMOUS, host, null, null); + return new GithubAuthData(AuthType.ANONYMOUS, host, null, null, true); } public static GithubAuthData createBasicAuth(@NotNull String host, @NotNull String login, @NotNull String password) { - return new GithubAuthData(AuthType.BASIC, host, new BasicAuth(login, password), null); + return new GithubAuthData(AuthType.BASIC, host, new BasicAuth(login, password), null, true); } public static GithubAuthData createTokenAuth(@NotNull String host, @NotNull String token) { - return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token)); + return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token), true); + } + + public static GithubAuthData createTokenAuth(@NotNull String host, @NotNull String token, boolean useProxy) { + return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token), useProxy); } @NotNull @@ -83,6 +91,10 @@ public class GithubAuthData { return myTokenAuth; } + public boolean isUseProxy() { + return myUseProxy; + } + public static class BasicAuth { @NotNull private final String myLogin; @NotNull private final String myPassword; From 4b8f2e5343160e2bc897fcbd6f66a1e1e48aa1c0 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Aug 2013 15:40:21 +0400 Subject: [PATCH 10/13] Github: change layout --- .../plugins/github/tasks/GithubRepositoryEditor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java index 5d6d8e5e0aeb..2a83c85a2d1f 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java @@ -74,6 +74,10 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor Date: Mon, 19 Aug 2013 15:41:47 +0400 Subject: [PATCH 11/13] Github: change action title --- .../plugins/github/GithubShowCommitInBrowserAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java index 1dc7aad02064..6795c6713426 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java @@ -32,7 +32,7 @@ import org.jetbrains.plugins.github.util.GithubUtil; abstract class GithubShowCommitInBrowserAction extends DumbAwareAction { public GithubShowCommitInBrowserAction() { - super("Open in Browser", "Open the selected commit in browser", GithubIcons.Github_icon); + super("Open op GitHub", "Open the selected commit in browser", GithubIcons.Github_icon); } protected static void openInBrowser(Project project, GitRepository repository, String revisionHash) { From e0e66bafeaf8ca0808c1589ad3704eb6008eb104 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Aug 2013 16:49:37 +0400 Subject: [PATCH 12/13] Github: extract function --- .../github/GithubOpenInBrowserAction.java | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index 4399bae08cf7..5729c98b598b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -92,10 +92,20 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { public void actionPerformed(final AnActionEvent e) { final Project project = e.getData(PlatformDataKeys.PROJECT); final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); + final Editor editor = e.getData(PlatformDataKeys.EDITOR); if (virtualFile == null || project == null || project.isDisposed()) { return; } + String urlToOpen = getGithubUrl(project, virtualFile, editor); + if (urlToOpen != null) { + BrowserUtil.launchBrowser(urlToOpen); + } + } + + @Nullable + public static String getGithubUrl(@NotNull Project project, @NotNull VirtualFile virtualFile, @Nullable Editor editor) { + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); final GitRepository repository = manager.getRepositoryForFile(virtualFile); if (repository == null) { @@ -104,13 +114,13 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { details.append(repo.getPresentableUrl()).append("; "); } GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find git repository", details.toString()); - return; + return null; } final String githubRemoteUrl = GithubUtil.findGithubRemoteUrl(repository); if (githubRemoteUrl == null) { GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find github remote"); - return; + return null; } final String rootPath = repository.getRoot().getPath(); @@ -118,25 +128,28 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { if (!path.startsWith(rootPath)) { GithubNotifications .showError(project, CANNOT_OPEN_IN_BROWSER, "File is not under repository root", "Root: " + rootPath + ", file: " + path); - return; + return null; } String branch = getBranchNameOnRemote(project, repository); if (branch == null) { - return; + return null; } String relativePath = path.substring(rootPath.length()); - String urlToOpen = makeUrlToOpen(e, relativePath, branch, githubRemoteUrl); + String urlToOpen = makeUrlToOpen(editor, relativePath, branch, githubRemoteUrl); if (urlToOpen == null) { GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, "Can't create properly url", githubRemoteUrl); - return; + return null; } - BrowserUtil.launchBrowser(urlToOpen); + + return urlToOpen; } @Nullable - private static String makeUrlToOpen(@NotNull AnActionEvent e, @NotNull String relativePath, @NotNull String branch, + private static String makeUrlToOpen(@Nullable Editor editor, + @NotNull String relativePath, + @NotNull String branch, @NotNull String githubRemoteUrl) { final StringBuilder builder = new StringBuilder(); final String githubRepoUrl = GithubUrlUtil.makeGithubRepoUrlFromRemoteUrl(githubRemoteUrl); @@ -145,7 +158,6 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { } builder.append(githubRepoUrl).append("/blob/").append(branch).append(relativePath); - final Editor editor = e.getData(PlatformDataKeys.EDITOR); if (editor != null && editor.getDocument().getLineCount() >= 1) { // lines are counted internally from 0, but from 1 on github SelectionModel selectionModel = editor.getSelectionModel(); From f27a8ea87be16763259a0c5d948891a850e03b0c Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Aug 2013 16:55:37 +0400 Subject: [PATCH 13/13] Github: add WebBrowserUrlProvider --- plugins/github/github.iml | 2 + plugins/github/src/META-INF/plugin.xml | 1 + .../GithubWebBrowserUrlProvider.java | 44 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java diff --git a/plugins/github/github.iml b/plugins/github/github.iml index ea922cfeadc6..50d0f799fcc2 100644 --- a/plugins/github/github.iml +++ b/plugins/github/github.iml @@ -20,6 +20,8 @@ + + diff --git a/plugins/github/src/META-INF/plugin.xml b/plugins/github/src/META-INF/plugin.xml index 86240aa4e428..4af448e9e741 100644 --- a/plugins/github/src/META-INF/plugin.xml +++ b/plugins/github/src/META-INF/plugin.xml @@ -19,6 +19,7 @@ + diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java new file mode 100644 index 000000000000..3ae08d0563fd --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2013 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.github.extensions; + +import com.intellij.ide.browsers.Url; +import com.intellij.ide.browsers.UrlImpl; +import com.intellij.ide.browsers.WebBrowserUrlProvider; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.github.GithubOpenInBrowserAction; + +/** + * @author Aleksey Pivovarov + */ +public class GithubWebBrowserUrlProvider extends WebBrowserUrlProvider { + @Nullable + @Override + public Url getUrl(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull VirtualFile virtualFile) throws BrowserException { + String url = GithubOpenInBrowserAction.getGithubUrl(element.getProject(), virtualFile, null); + return new UrlImpl(url, "https", null, null, null); + } + + @Nullable + @Override + public String getOpenInBrowserActionText(@NotNull PsiFile file) { + return "Open on GitHub"; + } +}