Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2019-04-17 11:55:40 +02:00
17 changed files with 535 additions and 314 deletions
@@ -14,6 +14,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.codeInspection.dataFlow.value.VariableDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
@@ -91,7 +92,7 @@ public class TrackingRunner extends StandardDataFlowRunner {
public static class CauseItem {
final @NotNull List<CauseItem> myChildren;
final @NotNull DfaProblemType myProblem;
final @Nullable PsiElement myTarget;
final @Nullable SmartPsiElementPointer<PsiElement> myTarget;
CauseItem(@NotNull String problem, @Nullable PsiElement target) {
this(new CustomDfaProblemType(problem), target);
@@ -100,7 +101,7 @@ public class TrackingRunner extends StandardDataFlowRunner {
CauseItem(@NotNull DfaProblemType problem, @Nullable PsiElement target) {
myChildren = new ArrayList<>();
myProblem = problem;
myTarget = target;
myTarget = target == null ? null : SmartPointerManager.createPointer(target);
}
CauseItem(@NotNull String problem, @NotNull MemoryStateChange change) {
@@ -135,7 +136,8 @@ public class TrackingRunner extends StandardDataFlowRunner {
}
private String dump(Document doc, int indent) {
return StringUtil.repeat(" ", indent) + render(doc) + (myTarget == null ? "" : " (" + myTarget.getText() + ")") + "\n" +
PsiElement target = myTarget != null ? myTarget.getElement() : null;
return StringUtil.repeat(" ", indent) + render(doc) + (target == null ? "" : " (" + target.getText() + ")") + "\n" +
StreamEx.of(myChildren).map(child -> child.dump(doc, indent + 1)).joining();
}
@@ -144,15 +146,20 @@ public class TrackingRunner extends StandardDataFlowRunner {
}
@Nullable
public PsiElement getTarget() {
return myTarget;
public PsiFile getFile() {
return myTarget != null ? myTarget.getContainingFile() : null;
}
public Segment getTargetSegment() {
return myTarget == null ? null : myTarget.getRange();
}
public String render(Document doc) {
if (myTarget != null) {
Segment range = getTargetSegment();
if (range != null) {
String cause = myProblem.toString();
if (cause.endsWith("#ref")) {
int offset = myTarget.getTextRange().getStartOffset();
int offset = range.getStartOffset();
int number = doc.getLineNumber(offset);
return cause.replaceFirst("#ref$", "line #" + (number + 1));
}
@@ -10,6 +10,8 @@ import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.dataFlow.TrackingRunner;
import com.intellij.ide.util.PsiNavigationSupport;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -19,9 +21,13 @@ import com.intellij.openapi.ui.popup.JBPopupAdapter;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiFile;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.EntryStream;
import org.jetbrains.annotations.Nls;
@@ -62,22 +68,28 @@ public class FindDfaProblemCauseFix implements LocalQuickFix, LowPriorityAction
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
ApplicationManager.getApplication().executeOnPooledThread(() -> ReadAction.run(this::findCause));
}
private void findCause() {
PsiExpression element = myAnchor.getElement();
if (element == null) return;
PsiFile file = element.getContainingFile();
List<TrackingRunner.CauseItem> items =
TrackingRunner.findProblemCause(myUnknownMembersAsNullable, myIgnoreAssertStatements, element, myProblemType);
ApplicationManager.getApplication().invokeLater(() -> ReadAction.run(() -> displayProblemCause(file, items)));
}
private static void displayProblemCause(PsiFile file, List<TrackingRunner.CauseItem> items) {
if (!file.isValid()) return;
Project project = file.getProject();
Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
if (editor == null) return;
Document document = editor.getDocument();
PsiFile file = element.getContainingFile();
PsiFile topLevelFile = InjectedLanguageManager.getInstance(project).getTopLevelFile(file);
if (topLevelFile == null || document != topLevelFile.getViewProvider().getDocument()) return;
List<TrackingRunner.CauseItem> items =
TrackingRunner.findProblemCause(myUnknownMembersAsNullable, myIgnoreAssertStatements, element, myProblemType);
TrackingRunner.CauseItem root = ContainerUtil.getOnlyItem(items);
if (root == null) {
HintManagerImpl hintManager = (HintManagerImpl)HintManager.getInstance();
hintManager.showErrorHint(editor, "Unable to find the cause");
return;
}
class CauseWithDepth {
final int myDepth;
final TrackingRunner.CauseItem myCauseItem;
@@ -92,8 +104,12 @@ public class FindDfaProblemCauseFix implements LocalQuickFix, LowPriorityAction
return StringUtil.repeat(" ", myDepth - 1) + myCauseItem.render(document);
}
}
List<CauseWithDepth> causes =
EntryStream.ofTree(root, (depth, c) -> c.children()).skip(1).mapKeyValue((d, i) -> new CauseWithDepth(d, i)).toList();
List<CauseWithDepth> causes;
if (root == null) {
causes = Collections.emptyList();
} else {
causes = EntryStream.ofTree(root, (depth, c) -> c.children()).skip(1).mapKeyValue((d, i) -> new CauseWithDepth(d, i)).toList();
}
if (causes.isEmpty()) {
HintManagerImpl hintManager = (HintManagerImpl)HintManager.getInstance();
hintManager.showErrorHint(editor, "Unable to find the cause");
@@ -117,9 +133,9 @@ public class FindDfaProblemCauseFix implements LocalQuickFix, LowPriorityAction
if (h == null) return;
h.dropHighlight();
if (cause == null) return;
PsiElement target = cause.myCauseItem.getTarget();
if (target == null || !target.isValid()) return;
TextRange range = target.getTextRange();
Segment target = cause.myCauseItem.getTargetSegment();
if (target == null) return;
TextRange range = TextRange.create(target);
h.highlight(Pair.create(range, Collections.singletonList(range)));
})
.addListener(new JBPopupAdapter() {
@@ -134,10 +150,9 @@ public class FindDfaProblemCauseFix implements LocalQuickFix, LowPriorityAction
}
private static void navigate(Editor editor, PsiFile file, TrackingRunner.CauseItem item) {
PsiElement target = item.getTarget();
if (target == null) return;
TextRange range = target.getTextRange();
PsiFile targetFile = target.getContainingFile();
Segment range = item.getTargetSegment();
if (range == null) return;
PsiFile targetFile = item.getFile();
assert targetFile == file;
PsiNavigationSupport.getInstance().createNavigatable(file.getProject(), targetFile.getVirtualFile(), range.getStartOffset())
.navigate(true);
@@ -8,21 +8,21 @@
},
"//": "https://github.com/amcharts/amcharts4/issues/1101",
"dependencies": {
"@amcharts/amcharts4": "4.3.7",
"@amcharts/amcharts4": "4.3.14",
"element-ui": "^2.7.2",
"semver": "^6.0.0",
"vue": "^2.6.10",
"vue-class-component": "^7.0.2",
"vue-property-decorator": "^8.1.0",
"vue-router": "^3.0.2",
"vue-router": "^3.0.5",
"vuex": "^3.1.0",
"vuex-persist": "^2.0.0"
},
"devDependencies": {
"@types/semver": "^6.0.0",
"@vue/cli-plugin-typescript": "^3.5.3",
"@vue/cli-service": "^3.5.3",
"typescript": "^3.4.1",
"@vue/cli-plugin-typescript": "^3.6.0",
"@vue/cli-service": "^3.6.0",
"typescript": "^3.4.3",
"vue-template-compiler": "^2.6.10",
"vuex-module-decorators": "^0.9.8"
},
@@ -14,9 +14,9 @@
</noscript>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.3.7/dist/script/core.js" integrity="sha384-RPBYt9CzNK7i9bzkJqL5ayYrt1cZ+oLkc1kwGPJcIprMHqRy0ciIA9Cb7kZxzkMc" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.3.7/dist/script/charts.js" integrity="sha384-LW1ZaR1KeHYBryxxAZsT8444nFxDpmo5k9wMZDy4g41U/d4LzQ7T9rd3IMWxGQt7" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.3.7/dist/script/themes/animated.js" integrity="sha384-06o6Xb/SVE8h4LpXotDV1+QRyW1j+OYHKOQRlKA7k0VkHYTTrXjXLx3eRxpvrdq1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.3.14/dist/script/core.js" integrity="sha384-tzk8F9qweBa3RPODqd2ZstOVlll0bjlB/S9PVdByzQ6kPLx7PKiyXw+QY4egfHuh" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.3.14/dist/script/charts.js" integrity="sha384-H0Gh034mb+w58CLQxBmGEo7s/LaLpsDn2DddFKXBplMS1d+aItwagD9XFOpuSS0V" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.3.14/dist/script/themes/animated.js" integrity="sha384-06o6Xb/SVE8h4LpXotDV1+QRyW1j+OYHKOQRlKA7k0VkHYTTrXjXLx3eRxpvrdq1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/amcharts/amcharts4@4.1.14/dist/script/plugins/sunburst.js" integrity="sha384-BrSNlpkmwEOIRnVc3YEpwikkpcBZ7Xn2cNEkMf3f1Ng9bspdUyPkIzYzOfCWsEg5" crossorigin="anonymous"></script>
<!-- built files will be auto injected -->
@@ -5,9 +5,10 @@
<script lang="ts">
import {Component, Prop, Watch} from "vue-property-decorator"
import {ActivityChartManager, ComponentChartManager} from "./ActivityChartManager"
import {ActivityChartManager} from "./ActivityChartManager"
import {ActivityChartType, chartDescriptors} from "@/charts/ActivityChartDescriptor"
import {BaseChartComponent} from "@/charts/BaseChartComponent"
import {ComponentChartManager} from "@/charts/ComponentChartManager"
@Component
export default class ActivityChart extends BaseChartComponent<ActivityChartManager> {
@@ -45,7 +45,7 @@ export class ActivityChartManager extends XYChartManager {
nameAxisLabel.selectable = true
nameAxisLabel.fontSize = 12
// quite useful to have tooltips also on axis labels (user report: they're easy to target with mouse)
nameAxisLabel.tooltipText = "{name}: {duration} ms\nrange: {start}-{end}"
nameAxisLabel.tooltipText = this.getTooltipText()
// https://github.com/amcharts/amcharts4/issues/997
nameAxisLabel.rotation = -45
@@ -84,10 +84,14 @@ export class ActivityChartManager extends XYChartManager {
series.dataFields.categoryX = "shortName"
series.dataFields.valueY = "duration"
series.columns.template.configField = "chartConfig"
series.columns.template.tooltipText = "{name}: {duration} ms\nrange: {start}-{end}\nthread: {thread}"
series.columns.template.tooltipText = this.getTooltipText()
}
// https://www.amcharts.com/docs/v4/concepts/series/#Note_about_Series_data_and_Category_axis
protected getTooltipText() {
return "{name}: {duration} ms\nrange: {start}-{end}\nthread: {thread}"
}
// https://www.amcharts.com/docs/v4/concepts/series/#Note_about_Series_data_and_Category_axis
render(data: DataManager): void {
const concatenatedData: Array<ClassItem> = []
let colorIndex = 0
@@ -119,12 +123,7 @@ export class ActivityChartManager extends XYChartManager {
applicableSources.add(sourceName)
for (const item of items) {
concatenatedData.push({
...item,
shortName: getShortName(item),
chartConfig,
sourceName,
})
concatenatedData.push(this.transformDataItem(item, chartConfig, sourceName, items))
}
}
@@ -147,6 +146,15 @@ export class ActivityChartManager extends XYChartManager {
this.chart.data = concatenatedData
}
protected transformDataItem(item: Item, chartConfig: ClassItemChartConfig, sourceName: string, _items: Array<Item>): ClassItem {
return {
...item,
shortName: getShortName(item),
chartConfig,
sourceName,
}
}
private sourceNameToLegendName(sourceName: string, itemCount: number): string {
let prefix
if (sourceName.startsWith("app")) {
@@ -199,31 +207,20 @@ function getShortName(item: Item): string {
return lastDotIndex < 0 ? item.name : item.name.substring(lastDotIndex + 1)
}
export class ComponentChartManager extends ActivityChartManager {
constructor(container: HTMLElement, sourceNames: Array<string>) {
super(container, sourceNames)
}
// doesn't make sense for components - cannot be outside of ready, and app initialized is clear
// because color for app/project bars is different
protected computeRangeMarkers(_data: DataManager) {
}
}
interface LegendItem {
readonly name: string
readonly sourceName: string
readonly fill: am4core.Color
}
interface ClassItem extends Item {
export interface ClassItem extends Item {
readonly shortName: string
readonly chartConfig: ClassItemChartConfig
readonly sourceName: string
}
interface ClassItemChartConfig {
export interface ClassItemChartConfig {
readonly fill: am4core.Color
readonly stroke: am4core.Color
}
@@ -0,0 +1,29 @@
// Copyright 2000-2019 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.
import {DataManager} from "@/state/DataManager"
import {ActivityChartManager, ClassItem, ClassItemChartConfig} from "@/charts/ActivityChartManager"
import {Item} from "@/state/data"
export class ComponentChartManager extends ActivityChartManager {
constructor(container: HTMLElement, sourceNames: Array<string>) {
super(container, sourceNames)
}
// doesn't make sense for components - cannot be outside of ready, and app initialized is clear
// because color for app/project bars is different
protected computeRangeMarkers(_data: DataManager) {
}
protected transformDataItem(item: Item, chartConfig: ClassItemChartConfig, sourceName: string, items: Array<Item>): ClassItem {
const result = super.transformDataItem(item, chartConfig, sourceName, items);
(result as ComponentItem).totalDuration = item.end - item.start
return result
}
protected getTooltipText() {
return super.getTooltipText() + "\ntotal duration: {totalDuration} ms"
}
}
interface ComponentItem extends ClassItem {
totalDuration: number
}
File diff suppressed because it is too large Load Diff
@@ -5,6 +5,7 @@ import com.intellij.diagnostic.Activity;
import com.intellij.diagnostic.ParallelActivity;
import com.intellij.diagnostic.PluginException;
import com.intellij.diagnostic.StartUpMeasurer;
import com.intellij.diagnostic.StartUpMeasurer.Level;
import com.intellij.diagnostic.StartUpMeasurer.Phases;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.openapi.application.Application;
@@ -481,7 +482,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
return instance;
}
long startTime = StartUpMeasurer.getCurrentTime();
Activity activity = createMeasureActivity(picoContainer);
instance = super.getComponentInstance(picoContainer);
if (myInitializing) {
@@ -509,7 +510,9 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
((BaseComponent)instance).initComponent();
}
ParallelActivity.COMPONENT.record(startTime, instance.getClass(), DefaultPicoContainer.getActivityLevel(picoContainer));
if (activity != null) {
activity.end();
}
}
finally {
myInitializing = false;
@@ -527,6 +530,15 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
return instance;
}
@Nullable
private Activity createMeasureActivity(@NotNull PicoContainer picoContainer) {
Level level = DefaultPicoContainer.getActivityLevel(picoContainer);
if (level == Level.APPLICATION || (level == Level.PROJECT && activityNamePrefix() != null)) {
return ParallelActivity.COMPONENT.start(getComponentImplementation().getName(), level);
}
return null;
}
@Override
public String toString() {
return "ComponentConfigAdapter[" + getComponentKey() + "]: implementation=" + getComponentImplementation() + ", plugin=" + myPluginId;
@@ -5,9 +5,7 @@ package com.intellij.execution;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.impl.ExecutionManagerImpl;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.execution.process.*;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunContentManager;
import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
@@ -23,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
@@ -42,6 +41,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -416,17 +416,26 @@ public class ExecutionHelper {
};
}
private static Runnable createTimeLimitedExecutionProcess(final ProcessHandler processHandler,
final ExecutionMode mode,
private static Runnable createTimeLimitedExecutionProcess(@NotNull ProcessHandler processHandler,
@NotNull ExecutionMode mode,
@NotNull final String presentableCmdline) {
List<String> outputCollected = new ArrayList<>();
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
if (StringUtil.isNotEmpty(event.getText())) {
outputCollected.add(outputType.toString() + ": " + event.getText());
}
}
});
return new Runnable() {
private final Semaphore mySemaphore = new Semaphore();
private final Runnable myProcessThread = () -> {
private final Runnable myProcessRunnable = () -> {
try {
final boolean finished = processHandler.waitFor(1000L * mode.getTimeout());
if (!finished) {
mode.getTimeoutCallback().consume(mode, presentableCmdline);
mode.onTimeout(processHandler, presentableCmdline, new ArrayList<>(outputCollected));
processHandler.destroyProcess();
}
}
@@ -438,7 +447,7 @@ public class ExecutionHelper {
@Override
public void run() {
mySemaphore.down();
ApplicationManager.getApplication().executeOnPooledThread(myProcessThread);
ApplicationManager.getApplication().executeOnPooledThread(myProcessRunnable);
OSProcessHandler.checkEdtAndReadAction(processHandler);
mySemaphore.waitFor();
}
@@ -15,10 +15,12 @@
*/
package com.intellij.execution;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessListener;
import com.intellij.util.Function;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -60,6 +62,22 @@ public class ExecutionMode {
return -1;
}
/**
* Invoked on the {@code processHandler} waiting timeout by the execution helper.
*
* @param outputCollected output collected to the moment of timeout (if any)
* @see ExecutionHelper#createTimeLimitedExecutionProcess(com.intellij.execution.process.ProcessHandler, com.intellij.execution.ExecutionMode, java.lang.String)
*/
public void onTimeout(@NotNull ProcessHandler processHandler,
@NotNull String commandLineString,
@NotNull List<String> outputCollected) {
}
/**
* @deprecated override {@link #onTimeout(ProcessHandler, String, List)} instead
*/
@ApiStatus.ScheduledForRemoval(inVersion = "2019.3")
@Deprecated
@NotNull
public PairConsumer<ExecutionMode, String> getTimeoutCallback() {
return NOOP_CONSUMER;
@@ -15,22 +15,24 @@
*/
package com.intellij.execution;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PairConsumer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
/**
* @author Roman.Chernyatchik, oleg
*/
public class ExecutionModes {
private static final Logger LOG = Logger.getInstance(ExecutionMode.class);
private static final PairConsumer<ExecutionMode, String> DEFAULT_TIMEOUT_CALLBACK = (mode, presentableCmdLine) -> {
final String msg = "Timeout (" + mode.getTimeout() + " sec) on executing: " + presentableCmdLine;
LOG.error(msg);
};
private static final PairConsumer<ExecutionMode, String> DEFAULT_TIMEOUT_CALLBACK = (mode, presentableCmdLine) ->
LOG.error("Timeout (" + mode.getTimeout() + " sec) on executing: " + presentableCmdLine);
/**
* Process will be run in back ground mode
@@ -78,6 +80,11 @@ public class ExecutionModes {
this(cancelable, title2, timeout, DEFAULT_TIMEOUT_CALLBACK);
}
/**
* @deprecated use a constructor without a callback. Instead of callback, override {@link #onTimeout(ProcessHandler, String, List)}
*/
@ApiStatus.ScheduledForRemoval(inVersion = "2019.3")
@Deprecated
public SameThreadMode(final boolean cancelable,
@Nullable final String title2,
final int timeout,
@@ -115,6 +122,16 @@ public class ExecutionModes {
return myTimeout;
}
@Override
public void onTimeout(@NotNull ProcessHandler processHandler,
@NotNull String commandLineString,
@NotNull List<String> outputCollected) {
super.onTimeout(processHandler, commandLineString, outputCollected);
String output = outputCollected.isEmpty() ? "No output" : StringUtil.join(outputCollected, "\n");
LOG.error("Timeout (" + getTimeout() + " sec) on executing: " + commandLineString + "; output collected: " + output);
}
@Deprecated
@NotNull
@Override
public PairConsumer<ExecutionMode, String> getTimeoutCallback() {
@@ -25,7 +25,7 @@ abstract class SaveAndSyncHandler {
scheduleSave(SaveTask(onlyProject))
}
data class SaveTask(val onlyProject: Project? = null, val saveDocuments: Boolean = true, val forceSavingAllSettings: Boolean = false) {
data class SaveTask @JvmOverloads constructor(val onlyProject: Project? = null, val saveDocuments: Boolean = true, val forceSavingAllSettings: Boolean = false) {
fun isMoreGenericThan(other: SaveTask): Boolean {
return onlyProject == null && other.onlyProject != null && saveDocuments == other.saveDocuments && forceSavingAllSettings == other.forceSavingAllSettings
}
@@ -10,6 +10,7 @@ import com.intellij.ide.BrowserUtil
import com.intellij.ide.GeneralSettings
import com.intellij.ide.IdeBundle
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.SystemInfo
@@ -52,7 +53,7 @@ open class BrowserLauncherAppless : BrowserLauncher() {
private fun openOrBrowse(_url: String, browse: Boolean, project: Project? = null) {
val url = signUrl(_url.trim { it <= ' ' })
LOG.debug("opening [$url]")
LOG.debug { "opening [$url]" }
if (url.startsWith("mailto:") && Desktop.getDesktop().isSupported(Desktop.Action.MAIL)) {
try {
@@ -155,17 +155,19 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
}
private fun writeParallelActivities(activities: Map<String, MutableList<ActivityImpl>>, startTime: Long, writer: JsonWriter) {
val ownDurations = ObjectLongHashMap<ActivityImpl>()
// sorted to get predictable JSON
for (name in activities.keys.sorted()) {
val list = activities.getValue(name)
ownDurations.clear()
val ownDurations = ObjectLongHashMap<ActivityImpl>()
if (SystemProperties.getBooleanProperty("idea.perf.stats.component.own.time", false) && name.endsWith("Component")) {
list.sortWith(Comparator(::compareTime))
val list = activities.getValue(name)
StartUpPerformanceReporter.sortItems(list)
if (name.endsWith("Component")) {
computeOwnTime(list, ownDurations)
}
StartUpPerformanceReporter.sortItems(list)
writeActivities(list, startTime, writer, activityNameToJsonFieldName(name), ownDurations)
}
}
@@ -201,7 +203,11 @@ private fun computeOwnTime(list: MutableList<ActivityImpl>, ownDurations: Object
}
val actualTotalDurationForAll = list.last().end - list.first().start
LOG.assertTrue(computedDurationForAll == actualTotalDurationForAll, "computed: $computedDurationForAll, actual: ${actualTotalDurationForAll}")
val diff = actualTotalDurationForAll - computedDurationForAll
val diffInMs = TimeUnit.NANOSECONDS.toMillis(diff)
if (diff < 0 || diffInMs > 3) {
LOG.warn("computed: $computedDurationForAll, actual: ${actualTotalDurationForAll} (diff: $diff, diffInMs: $diffInMs)")
}
}
private fun isInclusive(otherItem: ActivityImpl, item: ActivityImpl): Boolean {
@@ -259,15 +265,19 @@ private fun writeActivities(activities: List<ActivityImpl>, offset: Long, writer
return
}
// actually here not all components, but only slow (>10ms - as it was before)
writer.name(fieldName)
writer.beginArray()
for (item in activities) {
val computedOwnDuration = ownDurations.get(item)
val duration = if (computedOwnDuration == -1L) item.end - item.start else computedOwnDuration
if (duration <= ParallelActivity.MEASURE_THRESHOLD) {
continue
}
writer.beginObject()
writer.name("name").value(item.name)
val computedOwnDuration = ownDurations.get(item)
writeItemTimeInfo(item, if (computedOwnDuration == -1L) item.end - item.start else computedOwnDuration, offset, writer)
writeItemTimeInfo(item, duration, offset, writer)
writer.endObject()
}
@@ -321,16 +331,16 @@ private fun writeUnknown(writer: JsonWriter, start: Long, end: Long, offset: Lon
return duration
}
private fun compareTime(o1: ActivityImpl, o2: ActivityImpl): Int {
return when {
o1.start > o2.start -> 1
o1.start < o2.start -> -1
else -> {
when {
o1.end > o2.end -> -1
o1.end < o2.end -> 1
else -> 0
}
private fun compareTime(o1: ActivityImpl, o2: ActivityImpl): Int {
return when {
o1.start > o2.start -> 1
o1.start < o2.start -> -1
else -> {
when {
o1.end > o2.end -> -1
o1.end < o2.end -> 1
else -> 0
}
}
}
}
@@ -15,7 +15,7 @@ public enum ParallelActivity {
POST_STARTUP_ACTIVITY("projectPostStartupActivity"),
;
private static final long MEASURE_THRESHOLD = TimeUnit.MILLISECONDS.toNanos(10);
public static final long MEASURE_THRESHOLD = TimeUnit.MILLISECONDS.toNanos(10);
private final String jsonName;
@@ -33,6 +33,11 @@ public enum ParallelActivity {
return ActivityImpl.createParallelActivity(this, name);
}
@NotNull
public Activity start(@NotNull String name, @NotNull StartUpMeasurer.Level level) {
return new ActivityImpl(name, /* description = */ null, StartUpMeasurer.getCurrentTime(), /* parent = */ null, level, this);
}
public long record(long start, @NotNull Class<?> clazz) {
return record(start, clazz, null);
}
@@ -3,6 +3,7 @@ package com.intellij.spellchecker;
import com.google.common.collect.Maps;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.ide.SaveAndSyncHandler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
@@ -258,6 +259,7 @@ public class SpellCheckerManager implements Disposable {
private void fireDictionaryChanged(@NotNull EditableDictionary dictionary) {
myUserDictionaryListenerEventDispatcher.getMulticaster().dictChanged(dictionary);
restartInspections();
SaveAndSyncHandler.getInstance().scheduleSave(new SaveAndSyncHandler.SaveTask(project, false), false);
project.save();
}