Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2016-09-05 13:56:55 +02:00
22 changed files with 377 additions and 218 deletions
@@ -44,6 +44,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* User: anna
@@ -123,17 +124,22 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
PsiBreakStatement.class, PsiReturnStatement.class, PsiThrowStatement.class);
if (exitPoints.isEmpty()) {
final List<PsiVariable> usedVariables = ControlFlowUtil.getUsedVariables(controlFlow, startOffset, endOffset);
for (PsiVariable variable : usedVariables) {
if (!HighlightControlFlowUtil.isEffectivelyFinal(variable, body, null)) {
return;
}
}
if (ExceptionUtil.getThrownCheckedExceptions(new PsiElement[]{body}).isEmpty()) {
TerminalBlock tb = TerminalBlock.from(statement.getIterationParameter(), body);
List<Operation> operations = tb.extractOperations();
final List<PsiVariable> nonFinalVariables = ControlFlowUtil.getUsedVariables(controlFlow, startOffset, endOffset)
.stream().filter(variable -> !HighlightControlFlowUtil.isEffectivelyFinal(variable, body, null))
.collect(Collectors.toList());
if(getCounter(statement, tb, operations, nonFinalVariables) != null) {
holder.registerProblem(iteratedValue, "Can be replaced with count() call",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new ReplaceWithCountFix());
}
if(!nonFinalVariables.isEmpty()) {
return;
}
if ((isArray || !isRawSubstitution(iteratedValueType, collectionClass)) && isCollectCall(tb, operations)) {
boolean addAll = operations.isEmpty() && isAddAllCall(tb);
holder.registerProblem(iteratedValue, "Can be replaced with " + (addAll ? "addAll call" : "collect call"),
@@ -169,6 +175,43 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
};
}
private static PsiExpression extractIncrementedExpression(PsiStatement statement) {
if(!(statement instanceof PsiExpressionStatement)) return null;
PsiExpression expression = ((PsiExpressionStatement)statement).getExpression();
PsiExpression operand;
if(expression instanceof PsiPostfixExpression) {
if(!JavaTokenType.PLUSPLUS.equals(((PsiPostfixExpression)expression).getOperationTokenType())) return null;
operand = ((PsiPostfixExpression)expression).getOperand();
} else if(expression instanceof PsiPrefixExpression) {
if(!JavaTokenType.PLUSPLUS.equals(((PsiPrefixExpression)expression).getOperationTokenType())) return null;
operand = ((PsiPrefixExpression)expression).getOperand();
} else return null; // TODO: support i = i+1;
return operand;
}
@Nullable
private static PsiLocalVariable getCounter(PsiForeachStatement foreachStatement,
TerminalBlock tb,
List<Operation> operations,
List<PsiVariable> variables) {
// have only one non-final variable
if(variables.size() != 1) return null;
// have single expression which is either ++x or x++
PsiExpression operand = extractIncrementedExpression(tb.getSingleStatement());
if(!(operand instanceof PsiReferenceExpression)) return null;
PsiElement element = ((PsiReferenceExpression)operand).resolve();
// the referred variable is the same as non-final variable
if(!(element instanceof PsiLocalVariable) || !variables.contains(element)) return null;
// the referred variable is not used in intermediate operations
for(Operation operation : operations) {
if(ReferencesSearch.search(element, new LocalSearchScope(operation.getExpression())).findFirst() != null) return null;
}
return (PsiLocalVariable)element;
}
private static boolean isAddAllCall(TerminalBlock tb) {
final PsiVariable variable = tb.getVariable();
final PsiMethodCallExpression methodCallExpression = tb.getSingleMethodCall();
@@ -288,6 +331,12 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
return mapperCall instanceof PsiReferenceExpression && ((PsiReferenceExpression)mapperCall).resolve() == variable;
}
private static void reformatWhenNeeded(@NotNull Project project, PsiElement result) {
if (result != null) {
CodeStyleManager.getInstance(project).reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(result));
}
}
private static class ReplaceWithForeachCallFix implements LocalQuickFix {
private final String myForEachMethodName;
@@ -476,12 +525,6 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
}
private static void reformatWhenNeeded(@NotNull Project project, PsiElement result) {
if (result != null) {
CodeStyleManager.getInstance(project).reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(result));
}
}
private static String createInitializerReplacementText(PsiType varType, PsiExpression initializer) {
final PsiType initializerType = initializer.getType();
final PsiClassType rawType = initializerType instanceof PsiClassType ? ((PsiClassType)initializerType).rawType() : null;
@@ -513,6 +556,65 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
private static class ReplaceWithCountFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return getFamilyName();
}
@NotNull
@Override
public String getFamilyName() {
return "Replace with count()";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiForeachStatement foreachStatement = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiForeachStatement.class);
if (foreachStatement != null) {
if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement)) return;
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiStatement body = foreachStatement.getBody();
final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
if (body != null && iteratedValue != null) {
final PsiParameter parameter = foreachStatement.getIterationParameter();
TerminalBlock tb = TerminalBlock.from(parameter, body);
List<String> intermediateOps = tb.extractOperationReplacements(elementFactory);
PsiExpression operand = extractIncrementedExpression(tb.getSingleStatement());
if(!(operand instanceof PsiReferenceExpression)) return;
PsiElement element = ((PsiReferenceExpression)operand).resolve();
if(!(element instanceof PsiLocalVariable)) return;
PsiLocalVariable var = (PsiLocalVariable)element;
final StringBuilder builder = generateStream(iteratedValue, intermediateOps);
builder.append(".count()");
PsiElement declaration = var.getParent();
if(declaration instanceof PsiDeclarationStatement) {
PsiElement[] elements = ((PsiDeclarationStatement)declaration).getDeclaredElements();
if(elements[elements.length-1] == var && foreachStatement.equals(
PsiTreeUtil.skipSiblingsForward(declaration, PsiWhiteSpace.class, PsiComment.class))) {
PsiExpression initializer = var.getInitializer();
if(initializer != null && initializer.getText().equals("0")) {
String typeStr = var.getType().getCanonicalText();
String replacement = (typeStr.equals("long") ? "" : "(" + typeStr + ") ") + builder;
initializer.replace(elementFactory.createExpressionFromText(replacement, foreachStatement));
simplifyRedundantCast(var);
foreachStatement.delete();
reformatWhenNeeded(project, var);
return;
}
}
}
PsiElement result = foreachStatement.replace(elementFactory.createStatementFromText(var.getName()+"+="+builder+";", foreachStatement));
simplifyRedundantCast(result);
reformatWhenNeeded(project, result);
}
}
}
}
/**
* Intermediate stream operation representation
*/
@@ -23,11 +23,12 @@ import com.intellij.lang.java.JavaDocumentationProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.util.Url;
import com.intellij.util.Urls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,6 +36,7 @@ import org.jetbrains.builtInWebServer.BuiltInServerOptions;
import org.jetbrains.builtInWebServer.WebServerPathToFileManager;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -111,14 +113,13 @@ public class JavaDocExternalFilter extends AbstractExternalFilter {
public String getExternalDocInfoForElement(@NotNull String docURL, final PsiElement element) throws Exception {
String externalDoc = null;
myElement = element;
String builtInServer = "http://localhost:" + BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort() + "/" + myProject.getName() + "/";
String projectPath = "/" + myProject.getName() + "/";
String builtInServer = "http://localhost:" + BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort() + projectPath;
if (docURL.startsWith(builtInServer)) {
int refPosition = docURL.lastIndexOf('#');
VirtualFile file = WebServerPathToFileManager.getInstance(myProject).findVirtualFile(
docURL.substring(builtInServer.length(), refPosition < builtInServer.length() ? docURL.length() : refPosition)
);
Url url = Urls.parseFromIdea(docURL);
VirtualFile file = url == null ? null : WebServerPathToFileManager.getInstance(myProject).findVirtualFile(url.getPath().substring(projectPath.length()));
if (file != null) {
InputStreamReader reader = new InputStreamReader(file.getInputStream(), CharsetToolkit.UTF8_CHARSET);
InputStreamReader reader = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
StringBuilder result = new StringBuilder();
try {
doBuildFromStream(docURL, reader, result);
@@ -0,0 +1,10 @@
// "Replace with count()" "true"
import java.util.Arrays;
public class Main {
public long test(String[] array) {
long longStrings = Arrays.stream(array).map(String::trim).filter(trimmed -> trimmed.length() > 10).count();
return longStrings;
}
}
@@ -0,0 +1,14 @@
// "Replace with count()" "true"
import java.util.List;
import java.util.Set;
public class Main {
public void test(List<Set<String>> nested) {
int count = 0;
for(Set<String> element : nested) {
if(element != null) {
count += element.stream().filter(str -> str.startsWith("xyz")).count();
}
}
}
}
@@ -0,0 +1,10 @@
// "Replace with count()" "true"
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class Main {
public void test(List<Set<String>> nested) {
int count = (int) nested.stream().filter(element -> element != null).flatMap(Collection::stream).filter(str -> str.startsWith("xyz")).count();
}
}
@@ -0,0 +1,14 @@
// "Replace with count()" "true"
public class Main {
public long test(String[] array) {
long longStrings = 0;
for(String str : a<caret>rray) {
String trimmed = str.trim();
if(trimmed.length() > 10) {
longStrings++;
}
}
return longStrings;
}
}
@@ -0,0 +1,18 @@
// "Replace with count()" "true"
import java.util.List;
import java.util.Set;
public class Main {
public void test(List<Set<String>> nested) {
int count = 0;
for(Set<String> element : nested) {
if(element != null) {
for(String str : eleme<caret>nt) {
if(str.startsWith("xyz")) {
count++;
}
}
}
}
}
}
@@ -0,0 +1,18 @@
// "Replace with count()" "true"
import java.util.List;
import java.util.Set;
public class Main {
public void test(List<Set<String>> nested) {
int count = 0;
for(Set<String> element : neste<caret>d) {
if(element != null) {
for(String str : element) {
if(str.startsWith("xyz")) {
count++;
}
}
}
}
}
}
@@ -53,7 +53,7 @@ internal class DefaultProjectStoreImpl(override val project: ProjectImpl, privat
override fun createSaveSession(states: StateMap) = object : FileBasedStorage.FileSaveSession(states, this) {
override fun saveLocally(element: Element?) {
super.saveLocally(Element("application").addContent(Element("component").setAttribute("name", "ProjectManager").addContent(element)))
super.saveLocally(element?.let { Element("application").addContent(Element("component").setAttribute("name", "ProjectManager").addContent(it))})
}
}
}
@@ -77,7 +77,7 @@ fun stateToElement(key: String, state: Any?, newLiveStates: Map<String, Element>
return state.clone()
}
else {
return newLiveStates?.get(key) ?: (state as? ByteArray)?.let { unarchiveState(it) }
return newLiveStates?.get(key) ?: (state as? ByteArray)?.let(::unarchiveState)
}
}
@@ -201,7 +201,15 @@ private fun save(states: StateMap, rootElementName: String?, newLiveStates: Map<
val rootElement = if (rootElementName == null) null else Element(rootElementName)
for (componentName in states.keys()) {
val element = states.getElement(componentName, newLiveStates) ?: continue
val element: Element
try {
element = states.getElement(componentName, newLiveStates) ?: continue
}
catch (e: Exception) {
LOG.error("Cannot save \"$componentName\" data", e)
continue
}
// name attribute should be first
val elementAttributes = element.attributes
if (elementAttributes.isEmpty()) {
@@ -29,7 +29,7 @@ import java.util.concurrent.atomic.AtomicReference
/**
* requestor is deprecated. Never use it in new code.
*/
data class CredentialAttributes(val serviceName: String, val userName: String? = null, val requestor: Class<*>? = null) {
data class CredentialAttributes @JvmOverloads constructor(val serviceName: String, val userName: String? = null, val requestor: Class<*>? = null) {
}
// user cannot be empty, but password can be
@@ -38,6 +38,8 @@ class Credentials(user: String?, val password: OneTimeString? = null) {
constructor(user: String?, password: CharArray?) : this(user, password?.let { OneTimeString(it) })
constructor(user: String?, password: ByteArray?) : this(user, password?.let { OneTimeString(password) })
val userName = user.nullize()
fun getPasswordAsString() = password?.toString()
@@ -19,14 +19,14 @@ package com.intellij.ui;
import com.intellij.openapi.editor.markup.TextAttributes;
import java.util.ArrayList;
import java.util.List;
public class HighlightedText {
private final StringBuffer myBuffer;
private final ArrayList myHighlightedRegions;
private final StringBuilder myBuffer;
private final List<HighlightedRegion> myHighlightedRegions = new ArrayList<>();
public HighlightedText() {
myBuffer = new StringBuffer();
myHighlightedRegions = new ArrayList(3);
myBuffer = new StringBuilder();
}
public void appendText(String text, TextAttributes attributes) {
@@ -37,16 +37,11 @@ public class HighlightedText {
}
}
public void insertTextAtStart(String text, TextAttributes attributes) {
int textLength = text.length();
for (int i=0; i < myHighlightedRegions.size(); i++) {
HighlightedRegion info = (HighlightedRegion)myHighlightedRegions.get(i);
info.startOffset += textLength;
info.endOffset += textLength;
}
myBuffer.insert(0, text);
public void appendText(char[] text, TextAttributes attributes) {
int startOffset = myBuffer.length();
myBuffer.append(text);
if (attributes != null) {
myHighlightedRegions.add(new HighlightedRegion(0, textLength, attributes));
myHighlightedRegions.add(new HighlightedRegion(startOffset, myBuffer.length(), attributes));
}
}
@@ -67,10 +62,8 @@ public class HighlightedText {
public void applyToComponent(HighlightableComponent renderer) {
renderer.setText(myBuffer.toString());
for (int i=0; i < myHighlightedRegions.size(); i++) {
HighlightedRegion info = (HighlightedRegion)myHighlightedRegions.get(i);
for (HighlightedRegion info : myHighlightedRegions) {
renderer.addHighlighter(info.startOffset, info.endOffset, info.textAttributes);
}
}
}
@@ -16,20 +16,18 @@
package com.intellij.ui;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.util.NotNullProducer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.PlatformColors;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
@@ -204,7 +202,7 @@ public class HyperlinkLabel extends HighlightableComponent {
@Override
public void handleText(char[] data, int pos) {
highlightedText.appendText(new String(data), currentAttributes);
highlightedText.appendText(data, currentAttributes);
}
@Override
@@ -41,21 +41,6 @@ public class AuthenticationDialog extends DialogWrapper {
init();
}
public AuthenticationDialog(String title, String description, final String login, final String password, final boolean rememberPassword) {
super(JOptionPane.getRootFrame(), true);
setTitle(title);
MnemonicHelper.init(getContentPane());
panel = new AuthenticationPanel(description, login, password, rememberPassword);
final Window window = getWindow();
if (window instanceof JDialog) {
((JDialog) window).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
}
init();
}
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
@@ -15,58 +15,43 @@
*/
package com.intellij.diagnostic;
import com.intellij.openapi.components.NamedComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.Base64;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import com.intellij.credentialStore.CredentialAttributes;
import com.intellij.credentialStore.Credentials;
import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.openapi.components.*;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.Nullable;
public class ErrorReportConfigurable implements JDOMExternalizable, NamedComponent {
public String ITN_LOGIN = "";
public String ITN_PASSWORD_CRYPT = "";
public boolean KEEP_ITN_PASSWORD = false;
import java.util.Base64;
public String EMAIL = "";
@State(name = "ErrorReportConfigurable", storages = @Storage(value = "other.xml", deprecated = true, roamingType = RoamingType.DISABLED))
class ErrorReportConfigurable implements PersistentStateComponent<ErrorReportConfigurable.State> {
public static final String SERVICE_NAME = "IntelliJ Platform — JetBrains Account";
static class State {
public String ITN_LOGIN;
public String ITN_PASSWORD_CRYPT;
}
public static ErrorReportConfigurable getInstance() {
return ServiceManager.getService(ErrorReportConfigurable.class);
}
@Nullable
@Override
public void readExternal(Element element) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, element);
if (!KEEP_ITN_PASSWORD) {
ITN_PASSWORD_CRYPT = "";
public State getState() {
return new State();
}
@Override
public void loadState(State state) {
if (!StringUtil.isEmpty(state.ITN_LOGIN) || !StringUtil.isEmpty(state.ITN_PASSWORD_CRYPT)) {
PasswordSafe.getInstance().set(new CredentialAttributes(SERVICE_NAME, state.ITN_LOGIN), new Credentials(state.ITN_LOGIN, Base64.getDecoder().decode(state.ITN_PASSWORD_CRYPT)));
}
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
String itnPassword = ITN_PASSWORD_CRYPT;
if (!KEEP_ITN_PASSWORD) {
ITN_PASSWORD_CRYPT = "";
}
DefaultJDOMExternalizer.writeExternal(this, element);
ITN_PASSWORD_CRYPT = itnPassword;
}
@Override
@NotNull
public String getComponentName() {
return "ErrorReportConfigurable";
}
public String getPlainItnPassword() {
return new String(Base64.decode(getInstance().ITN_PASSWORD_CRYPT), CharsetToolkit.UTF8_CHARSET);
}
public void setPlainItnPassword(String password) {
ITN_PASSWORD_CRYPT = Base64.encode(password.getBytes(CharsetToolkit.UTF8_CHARSET));
@Nullable
public static Credentials getCredentials() {
return PasswordSafe.getInstance().get(new CredentialAttributes(SERVICE_NAME));
}
}
@@ -16,6 +16,8 @@
package com.intellij.diagnostic;
import com.intellij.CommonBundle;
import com.intellij.credentialStore.CredentialAttributesKt;
import com.intellij.credentialStore.Credentials;
import com.intellij.errorreport.bean.ErrorBean;
import com.intellij.errorreport.error.InternalEAPException;
import com.intellij.errorreport.error.NoSuchEAPUserException;
@@ -28,7 +30,6 @@ import com.intellij.idea.IdeaLogger;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
@@ -77,15 +78,13 @@ public class ITNReporter extends ErrorReportSubmitter {
final Consumer<SubmittedReportInfo> callback,
final ErrorBean errorBean,
final String description) {
final DataContext dataContext = DataManager.getInstance().getDataContext(parentComponent);
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
ErrorReportConfigurable settings = ErrorReportConfigurable.getInstance();
if (!settings.KEEP_ITN_PASSWORD && !StringUtil.isEmpty(settings.ITN_LOGIN) && StringUtil.isEmpty(settings.getPlainItnPassword())) {
JetBrainsAccountDialog dlg = new JetBrainsAccountDialog(parentComponent);
if (!dlg.showAndGet()) {
Credentials credentials = ErrorReportConfigurable.getCredentials();
if (!CredentialAttributesKt.isFulfilled(credentials)) {
if (!new JetBrainsAccountDialog(parentComponent).showAndGet()) {
return false;
}
credentials = ErrorReportConfigurable.getCredentials();
}
errorBean.setDescription(description);
@@ -95,17 +94,7 @@ public class ITNReporter extends ErrorReportSubmitter {
errorBean.setPreviousException(previousExceptionThreadId);
}
Throwable t = event.getThrowable();
if (t != null) {
final PluginId pluginId = IdeErrorsDialog.findPluginId(t);
if (pluginId != null) {
final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(pluginId);
if (ideaPluginDescriptor != null && (!ideaPluginDescriptor.isBundled() || ideaPluginDescriptor.allowBundledUpdate())) {
errorBean.setPluginName(ideaPluginDescriptor.getName());
errorBean.setPluginVersion(ideaPluginDescriptor.getVersion());
}
}
}
setPluginInfo(event, errorBean);
Object data = event.getData();
if (data instanceof AbstractMessage) {
@@ -113,13 +102,14 @@ public class ITNReporter extends ErrorReportSubmitter {
errorBean.setAttachments(((AbstractMessage)data).getIncludedAttachments());
}
String login = settings.ITN_LOGIN;
String password = settings.getPlainItnPassword();
String login = credentials == null ? null : credentials.getUserName();
String password = credentials == null ? null : credentials.getPasswordAsString();
if (StringUtil.isEmptyOrSpaces(login) && StringUtil.isEmptyOrSpaces(password)) {
login = "idea_anonymous";
password = "guest";
}
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent));
ITNProxy.sendError(project, login, password, errorBean, threadId -> {
updatePreviousThreadId(threadId);
String url = ITNProxy.getBrowseUrl(threadId);
@@ -175,6 +165,20 @@ public class ITNReporter extends ErrorReportSubmitter {
return true;
}
public static void setPluginInfo(IdeaLoggingEvent event, ErrorBean errorBean) {
Throwable t = event.getThrowable();
if (t != null) {
final PluginId pluginId = IdeErrorsDialog.findPluginId(t);
if (pluginId != null) {
final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(pluginId);
if (ideaPluginDescriptor != null && (!ideaPluginDescriptor.isBundled() || ideaPluginDescriptor.allowBundledUpdate())) {
errorBean.setPluginName(ideaPluginDescriptor.getName());
errorBean.setPluginVersion(ideaPluginDescriptor.getVersion());
}
}
}
}
private static void updatePreviousThreadId(Integer threadId) {
previousExceptionThreadId = threadId;
}
@@ -17,6 +17,8 @@ package com.intellij.diagnostic;
import com.intellij.CommonBundle;
import com.intellij.ExtensionPoints;
import com.intellij.credentialStore.CredentialAttributesKt;
import com.intellij.credentialStore.Credentials;
import com.intellij.diagnostic.errordialog.*;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
@@ -52,7 +54,6 @@ import com.intellij.openapi.wm.IdeFrame;
import com.intellij.ui.HeaderlessTabbedPane;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
@@ -71,6 +72,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
@@ -80,7 +82,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
private static final Logger LOG = Logger.getInstance(IdeErrorsDialog.class.getName());
private final boolean myInternalMode;
@NonNls private static final String ACTIVE_TAB_OPTION = IdeErrorsDialog.class.getName() + "activeTab";
public static DataKey<String> CURRENT_TRACE_KEY = DataKey.create("current_stack_trace_key");
public static final DataKey<String> CURRENT_TRACE_KEY = DataKey.create("current_stack_trace_key");
public static final int COMPONENTS_WIDTH = 670;
public static Collection<Developer> ourDevelopersList = Collections.emptyList();
@@ -287,7 +289,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
}
};
if (!myInternalMode) {
myDetailsTabForm = new DetailsTabForm(null, myInternalMode);
myDetailsTabForm = new DetailsTabForm(null, false);
myCommentsTabForm = new CommentsTabForm();
myCommentsTabForm.addCommentsListener(commentsListener);
myTabs.addTab(DiagnosticBundle.message("error.comments.tab.title"), myCommentsTabForm.getContentPane());
@@ -298,7 +300,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
if (analyzePlatformAction != null) {
myAnalyzeAction = new AnalyzeAction(analyzePlatformAction);
}
myDetailsTabForm = new DetailsTabForm(myAnalyzeAction, myInternalMode);
myDetailsTabForm = new DetailsTabForm(myAnalyzeAction, true);
myDetailsTabForm.setCommentsAreaVisible(true);
myDetailsTabForm.addCommentsListener(commentsListener);
}
@@ -465,15 +467,16 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
private void updateCredentialsPane(AbstractMessage message) {
if (message != null) {
final ErrorReportSubmitter submitter = getSubmitter(message.getThrowable());
ErrorReportSubmitter submitter = getSubmitter(message.getThrowable());
if (submitter instanceof ITNReporter) {
myCredentialsPanel.setVisible(true);
String userName = ErrorReportConfigurable.getInstance().ITN_LOGIN;
if (StringUtil.isEmpty(userName)) {
myCredentialsLabel.setHtmlText(DiagnosticBundle.message("diagnostic.error.report.submit.error.anonymously"));
Credentials credentials = ErrorReportConfigurable.getCredentials();
if (CredentialAttributesKt.isFulfilled(credentials)) {
assert credentials != null;
myCredentialsLabel.setHtmlText(DiagnosticBundle.message("diagnostic.error.report.submit.report.as", credentials.getUserName()));
}
else {
myCredentialsLabel.setHtmlText(DiagnosticBundle.message("diagnostic.error.report.submit.report.as", userName));
myCredentialsLabel.setHtmlText(DiagnosticBundle.message("diagnostic.error.report.submit.error.anonymously"));
}
return;
}
@@ -647,7 +650,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
myDetailsTabForm.setAssigneeId(message == null ? null : message.getAssigneeId());
List<Attachment> attachments = message != null ? message.getAllAttachments() : Collections.<Attachment>emptyList();
List<Attachment> attachments = message != null ? message.getAllAttachments() : Collections.emptyList();
if (!attachments.isEmpty()) {
if (myTabs.indexOfComponent(myAttachmentsTabForm.getContentPane()) == -1) {
myTabs.addTab(DiagnosticBundle.message("error.attachments.tab.title"), myAttachmentsTabForm.getContentPane());
@@ -672,7 +675,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
return throwable.getMessage();
}
else {
return new StringBuffer().append(message.getMessage()).append("\n").append(message.getThrowableText()).toString();
return message.getMessage() + "\n" + message.getThrowableText();
}
}
@@ -767,8 +770,8 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
}
}
if (PluginManager.isPluginClass(className)) {
return PluginManager.getPluginByClassName(className);
if (PluginManagerCore.isPluginClass(className)) {
return PluginManagerCore.getPluginByClassName(className);
}
}
}
@@ -777,8 +780,8 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
if (t.getMessage() != null) {
String className = t.getMessage();
if (PluginManager.isPluginClass(className)) {
return PluginManager.getPluginByClassName(className);
if (PluginManagerCore.isPluginClass(className)) {
return PluginManagerCore.getPluginByClassName(className);
}
}
}
@@ -791,8 +794,8 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
pos = s.lastIndexOf('.');
if (pos >= 0) {
s = s.substring(0, pos);
if (PluginManager.isPluginClass(s)) {
return PluginManager.getPluginByClassName(s);
if (PluginManagerCore.isPluginClass(s)) {
return PluginManagerCore.getPluginByClassName(s);
}
}
}
@@ -800,8 +803,8 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
else if (t instanceof ExtensionException) {
String className = ((ExtensionException)t).getExtensionClass().getName();
if (PluginManager.isPluginClass(className)) {
return PluginManager.getPluginByClassName(className);
if (PluginManagerCore.isPluginClass(className)) {
return PluginManagerCore.getPluginByClassName(className);
}
}
@@ -1016,8 +1019,8 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
private static String md5(String buffer, @NonNls String key) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(buffer.getBytes());
byte[] code = md5.digest(key.getBytes());
md5.update(buffer.getBytes(StandardCharsets.UTF_8));
byte[] code = md5.digest(key.getBytes(StandardCharsets.UTF_8));
BigInteger bi = new BigInteger(code).abs();
return bi.abs().toString(16);
}
@@ -15,9 +15,13 @@
*/
package com.intellij.diagnostic;
import com.intellij.credentialStore.CredentialAttributes;
import com.intellij.credentialStore.Credentials;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ClickListener;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
@@ -28,20 +32,8 @@ import java.awt.event.MouseEvent;
public class JetBrainsAccountDialog extends DialogWrapper {
private JTextField myItnLoginTextField;
private JPasswordField myItnPasswordTextField;
private JCheckBox myRememberITNPasswordCheckBox;
public void storeInfo() {
ErrorReportConfigurable.getInstance().ITN_LOGIN = myItnLoginTextField.getText();
ErrorReportConfigurable.getInstance().setPlainItnPassword(new String(myItnPasswordTextField.getPassword()));
ErrorReportConfigurable.getInstance().KEEP_ITN_PASSWORD = myRememberITNPasswordCheckBox.isSelected();
}
public void loadInfo() {
myItnLoginTextField.setText(ErrorReportConfigurable.getInstance().ITN_LOGIN);
myItnPasswordTextField.setText(ErrorReportConfigurable.getInstance().getPlainItnPassword());
myRememberITNPasswordCheckBox.setSelected(ErrorReportConfigurable.getInstance().KEEP_ITN_PASSWORD);
}
private JPasswordField myPasswordText;
private JCheckBox myRememberCheckBox;
public JetBrainsAccountDialog(Component parent) throws HeadlessException {
super(parent, false);
@@ -82,7 +74,13 @@ public class JetBrainsAccountDialog extends DialogWrapper {
mySendingSettingsLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
loadInfo();
Credentials credentials = ErrorReportConfigurable.getCredentials();
String userName = credentials == null ? null : credentials.getUserName();
myItnLoginTextField.setText(userName);
String password = credentials == null ? null : credentials.getPasswordAsString();
myPasswordText.setText(password);
// if no user name - never stored and so, defaults to remember. if user name set, but no password, so, previously was stored without password
myRememberCheckBox.setSelected(StringUtil.isEmpty(userName) || !StringUtil.isEmpty(password));
new ClickListener() {
@Override
@@ -98,7 +96,11 @@ public class JetBrainsAccountDialog extends DialogWrapper {
@Override
protected void doOKAction() {
storeInfo();
String userName = myItnLoginTextField.getText();
if (!StringUtil.isEmpty(userName)) {
PasswordSafe.getInstance().set(new CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName),
new Credentials(userName, myRememberCheckBox.isSelected() ? myPasswordText.getPassword() : null));
}
super.doOKAction();
}
@@ -8,7 +8,7 @@
<properties/>
<border type="none"/>
<children>
<grid id="46178" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="46178" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="2" left="4" bottom="0" right="4"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -17,55 +17,11 @@
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="etched" title-resource-bundle="messages/DiagnosticBundle" title-key="diagnostic.error.report.login.group"/>
<border type="none"/>
<children>
<grid id="feb2" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<component id="4f69e" class="javax.swing.JCheckBox" binding="myRememberCheckBox">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="fbdcc" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="b3002"/>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.password"/>
</properties>
</component>
<component id="87071" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="e3ed"/>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.name"/>
</properties>
</component>
<component id="e3ed" class="javax.swing.JTextField" binding="myItnLoginTextField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b3002" class="javax.swing.JPasswordField" binding="myItnPasswordTextField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<component id="4f69e" class="javax.swing.JCheckBox" binding="myRememberITNPasswordCheckBox">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.remember.password.checkbox"/>
@@ -73,12 +29,46 @@
</component>
<component id="2c912" class="javax.swing.JLabel" binding="myCreateAccountLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&lt;html&gt;&lt;a href=&quot;#&quot;&gt;Create or manage your JetBrains Account&lt;/a&gt;&lt;/html&gt;"/>
</properties>
</component>
<component id="fbdcc" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="b3002"/>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.password"/>
</properties>
</component>
<component id="87071" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="e3ed"/>
<text resource-bundle="messages/DiagnosticBundle" key="diagnostic.error.report.login.name"/>
</properties>
</component>
<component id="e3ed" class="javax.swing.JTextField" binding="myItnLoginTextField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b3002" class="javax.swing.JPasswordField" binding="myPasswordText">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<component id="115f0" class="javax.swing.JLabel" binding="mySendingSettingsLabel">
@@ -16,7 +16,6 @@
package com.intellij.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
@@ -142,11 +141,14 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
public abstract static class RendererComponent extends CellRendererPanel implements Disposable {
private final EditorEx myEditor;
private final EditorTextField myTextField;
protected TextAttributes myTextAttributes;
private boolean mySelected;
public RendererComponent(Project project, @Nullable FileType fileType, boolean inheritFontFromLaF) {
myEditor = createEditor(project, fileType, inheritFontFromLaF);
Pair<EditorTextField, EditorEx> pair = createEditor(project, fileType, inheritFontFromLaF);
myTextField = pair.first;
myEditor = pair.second;
add(myEditor.getContentComponent());
}
@@ -155,7 +157,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
}
@NotNull
private static EditorEx createEditor(Project project, @Nullable FileType fileType, boolean inheritFontFromLaF) {
private static Pair<EditorTextField, EditorEx> createEditor(Project project, @Nullable FileType fileType, boolean inheritFontFromLaF) {
EditorTextField field = new EditorTextField(new MyDocument(), project, fileType, false, false);
field.setSupplementary(true);
field.setFontInheritedFromLAF(inheritFontFromLaF);
@@ -169,7 +171,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
editor.getScrollPane().setBorder(null);
return editor;
return Pair.create(field, editor);
}
public void setText(String text, @Nullable TextAttributes textAttributes, boolean selected) {
@@ -191,8 +193,8 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
@Override
public void dispose() {
myEditor.getComponent().removeNotify();
EditorFactory.getInstance().releaseEditor(myEditor);
remove(myEditor.getContentComponent());
myTextField.removeNotify();
}
protected void setTextToEditor(String text) {
@@ -1,7 +1,7 @@
<html>
<body>
This inspection reports foreach loops which can be replaced with stream api calls.
This inspection reports foreach loops which can be replaced with stream API calls.
<p>
Stream api is not available under Java 1.7 or earlier JVMs.
Stream API is not available under Java 1.7 or earlier JVMs.
</body>
</html>