Skip to content
Permalink
Browse files
[platform] refactoring of exception handling/reporting subsystem
- streamlines exception flow through the system
- allows message and stacktrace editing by user (IDEA-188535)
- deprecates methods/classes basically duplicating Logger.error(..)
- annotates and comments methods of AbstractMessage
  • Loading branch information
trespasserw committed May 30, 2018
1 parent 463c472 commit e10f08b8b954fdecb45fe0ba519e1eaf58c4ed02
Showing with 725 additions and 771 deletions.
  1. +40 −61 platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java
  2. +34 −41 platform/platform-impl/src/com/intellij/diagnostic/AttachmentFactory.java
  3. +31 −40 platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java
  4. +25 −38 platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java
  5. +108 −50 platform/platform-impl/src/com/intellij/diagnostic/ITNProxy.java
  6. +22 −28 platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt
  7. +195 −105 platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
  8. +10 −41 platform/platform-impl/src/com/intellij/diagnostic/IdeMessagePanel.java
  9. +69 −0 platform/platform-impl/src/com/intellij/diagnostic/IdeaReportingEvent.java
  10. +7 −22 platform/platform-impl/src/com/intellij/diagnostic/LogEventException.java
  11. +39 −66 platform/platform-impl/src/com/intellij/diagnostic/LogMessage.java
  12. +35 −115 platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java
  13. +13 −8 platform/platform-impl/src/com/intellij/diagnostic/MessagePool.java
  14. +6 −8 platform/platform-impl/src/com/intellij/errorreport/bean/ErrorBean.java
  15. +4 −11 platform/platform-impl/src/com/intellij/idea/IdeaLogger.java
  16. +30 −27 platform/platform-tests/testSrc/com/intellij/diagnostic/AttachmentFactoryTest.java
  17. +2 −16 platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestUtilKt.kt
  18. +34 −78 platform/util/src/com/intellij/openapi/diagnostic/Attachment.java
  19. +21 −16 platform/util/src/com/intellij/openapi/diagnostic/RuntimeExceptionWithAttachments.java
@@ -1,70 +1,58 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.diagnostic;

import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;

public abstract class AbstractMessage {

private boolean myIsRead = false;
private boolean myIsSubmitting = false;
private final Date myDate = Calendar.getInstance().getTime();
private boolean myIsRead;
private Runnable myOnReadCallback;
private boolean myIsSubmitting;
private SubmittedReportInfo mySubmissionInfo;
private String myAdditionalInfo;
private Runnable myOnReadCallback;
private Integer myAssigneeId;

private final Date myDate;
public abstract @NotNull Throwable getThrowable();
public abstract @NotNull String getThrowableText();

/** Returns a user message (see {@link LogMessage#createEvent}), if present. */
public abstract @Nullable String getMessage();

/** Returns a (possibly empty) list of all attachments. */
public @NotNull List<Attachment> getAllAttachments() {
return Collections.emptyList();
}

public AbstractMessage() {
myDate = Calendar.getInstance().getTime();
/** Returns a list of attachments marked by a user to be included into the error report. */
public @NotNull List<Attachment> getIncludedAttachments() {
return ContainerUtil.filter(getAllAttachments(), Attachment::isIncluded);
}

public abstract String getThrowableText();
public abstract Throwable getThrowable();
public abstract String getMessage();
public @NotNull Date getDate() {
return myDate;
}

public boolean isRead() {
return myIsRead;
}

public void setRead(boolean aReadFlag) {
myIsRead = aReadFlag;
if (myOnReadCallback != null && aReadFlag) {
public void setRead(boolean isRead) {
myIsRead = isRead;
if (isRead && myOnReadCallback != null) {
myOnReadCallback.run();
myOnReadCallback = null;
}
}

public void setSubmitted(SubmittedReportInfo info) {
myIsSubmitting = false;
mySubmissionInfo = info;
}

public SubmittedReportInfo getSubmissionInfo() {
return mySubmissionInfo;
}

public void setOnReadCallback(Runnable callback) {
myOnReadCallback = callback;
}
@@ -77,10 +65,19 @@ public void setSubmitting(boolean isSubmitting) {
myIsSubmitting = isSubmitting;
}

public SubmittedReportInfo getSubmissionInfo() {
return mySubmissionInfo;
}

public void setSubmitted(SubmittedReportInfo info) {
myIsSubmitting = false;
mySubmissionInfo = info;
}

public boolean isSubmitted() {
return mySubmissionInfo != null &&
(mySubmissionInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.NEW_ISSUE ||
mySubmissionInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.DUPLICATE);
(mySubmissionInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.NEW_ISSUE ||
mySubmissionInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.DUPLICATE);
}

public String getAdditionalInfo() {
@@ -91,34 +88,16 @@ public void setAdditionalInfo(String additionalInfo) {
myAdditionalInfo = additionalInfo;
}

public Date getDate() {
return myDate;
}

public Integer getAssigneeId() {
public @Nullable Integer getAssigneeId() {
return myAssigneeId;
}

public void setAssigneeId(Integer assigneeId) {
public void setAssigneeId(@Nullable Integer assigneeId) {
myAssigneeId = assigneeId;
}

public List<Attachment> getAllAttachments() {
return Collections.emptyList();
}

/**
* @return list of attachments which are marked by user to be included into the error report
*/
public List<Attachment> getIncludedAttachments() {
return ContainerUtil.filter(getAllAttachments(), Attachment::isIncluded);
}

/**
* @deprecated use {@link #getIncludedAttachments()} instead
*/
@NotNull
/** @deprecated use {@link #getIncludedAttachments()} instead (to be removed in IDEA 2020) */
public List<Attachment> getAttachments() {
return getIncludedAttachments();
}
}
}
@@ -1,3 +1,4 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.diagnostic;

import com.intellij.openapi.diagnostic.Attachment;
@@ -7,73 +8,65 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PathUtilRt;
import org.jetbrains.annotations.NotNull;

import java.io.*;
import java.text.MessageFormat;

/**
* @author yole
*/
public class AttachmentFactory {
private static final Logger LOG = Logger.getInstance(AttachmentFactory.class);

private static final Long BIG_FILE_THRESHOLD_BYTES = 50 * 1024L;
private static final long BIG_FILE_THRESHOLD_BYTES = 50 * 1024;

private static final String ERROR_MESSAGE_PATTERN = "[[[Can't get file contents: {0}]]]";
private static final String BIG_FILE_MESSAGE_PATTERN = "[[[File is too big to display: {0}]]]";
public static Attachment createContext(@NotNull Object start, Object... more) {
StringBuilder builder = new StringBuilder(String.valueOf(start));
for (Object o : more) builder.append(",").append(o);
return new Attachment("current-context.txt", builder.length() > 0 ? builder.toString() : "(unknown)");
}

public static Attachment createAttachment(Document document) {
public static Attachment createAttachment(@NotNull Document document) {
VirtualFile file = FileDocumentManager.getInstance().getFile(document);
return new Attachment(file != null ? file.getPath() : "unknown.txt", document.getText());
}

public static Attachment createAttachment(@NotNull VirtualFile file) {
try {
boolean isBinary = file.getFileType().isBinary();
boolean isBigFile = file.getLength() > BIG_FILE_THRESHOLD_BYTES;

try (InputStream inputStream = file.getInputStream()) {
return createAttachment(file.getPresentableUrl(), inputStream, isBinary, isBigFile);
}
} catch (IOException e) {
return handleException(e, file.getName(), file.getPath());
try (InputStream inputStream = file.getInputStream()) {
return createAttachment(file.getPresentableUrl(), inputStream, file.getLength(), file.getFileType().isBinary());
}
catch (IOException e) {
return handleException(e, file.getPath());
}
}

public static Attachment createAttachment(@NotNull File file, boolean isBinary) {
try {
try (InputStream inputStream = new FileInputStream(file)) {
return createAttachment(file.getPath(), inputStream, isBinary, file.length() > BIG_FILE_THRESHOLD_BYTES);
}
} catch (IOException e) {
return handleException(e, file.getName(), file.getPath());
try (InputStream inputStream = new FileInputStream(file)) {
return createAttachment(file.getPath(), inputStream, file.length(), isBinary);
}
catch (IOException e) {
return handleException(e, file.getPath());
}
}

private static Attachment handleException(Throwable t, String name, String moniker) {
final String errorMessage = MessageFormat.format(ERROR_MESSAGE_PATTERN, t.getMessage());

LOG.warn("Unable to create Attachment from " + moniker + ": " + t.getMessage(), t);
return new Attachment(name, errorMessage);
}

private static Attachment createAttachment(@NotNull String path, InputStream contentStream, boolean isBinary, boolean isBigFile) {
if (isBigFile) {
return new Attachment(path, contentStream, MessageFormat.format(BIG_FILE_MESSAGE_PATTERN, path));
} else {
byte[] bytes = getBytes(contentStream);
final String displayText = isBinary ? "[File is binary]" : new String(bytes, CharsetToolkit.UTF8_CHARSET);
return new Attachment(path, bytes, displayText);
}
private static Attachment handleException(Throwable t, String path) {
LOG.warn("failed to create an attachment from " + path, t);
return new Attachment(path, t);
}

private static byte[] getBytes(InputStream inputStream) {
try {
return FileUtil.loadBytes(inputStream);
private static Attachment createAttachment(String path, InputStream content, long contentLength, boolean isBinary) throws IOException {
if (contentLength >= BIG_FILE_THRESHOLD_BYTES) {
File tempFile = FileUtil.createTempFile("ij-attachment-" + PathUtilRt.getFileName(path) + ".", isBinary ? ".bin" : ".txt", true);
try (OutputStream outputStream = new FileOutputStream(tempFile)) {
FileUtil.copy(content, contentLength, outputStream);
}
return new Attachment(path, tempFile, "[File is too big to display]");
}
catch (IOException e) {
return MessageFormat.format(ERROR_MESSAGE_PATTERN, e.getMessage()).getBytes(CharsetToolkit.UTF8_CHARSET);
else {
byte[] bytes = FileUtil.loadBytes(content);
String displayText = isBinary ? "[File is binary]" : new String(bytes, CharsetToolkit.UTF8_CHARSET);
return new Attachment(path, bytes, displayText);
}
}
}
}

0 comments on commit e10f08b

Please sign in to comment.