package com.google.dart.dev.util.analysis;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.engine.context.AnalysisContextStatistics;
import com.google.dart.engine.context.AnalysisContextStatistics.CacheRow;
import com.google.dart.engine.context.AnalysisContextStatistics.PartitionData;
import com.google.dart.engine.context.AnalysisException;
import com.google.dart.engine.element.CompilationUnitElement;
import com.google.dart.engine.element.ExportElement;
import com.google.dart.engine.element.ImportElement;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.index.Index;
import com.google.dart.engine.internal.cache.CacheState;
import com.google.dart.engine.internal.cache.DataDescriptor;
import com.google.dart.engine.internal.cache.SourceEntryImpl;
import com.google.dart.engine.internal.context.InternalAnalysisContext;
import com.google.dart.engine.internal.context.PerformanceStatistics;
import com.google.dart.engine.internal.index.IndexImpl;
import com.google.dart.engine.internal.index.operation.OperationQueue;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.utilities.io.PrintStringWriter;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.core.DartCoreDebug;
import com.google.dart.tools.core.analysis.model.Project;
import com.google.dart.tools.core.analysis.model.PubFolder;
import com.google.dart.tools.core.internal.builder.AnalysisManager;
import com.google.dart.tools.core.internal.builder.AnalysisWorker;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.part.ViewPart;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
/**
* The view to display analysis statistics.
*/
public class AnalysisView extends ViewPart {
private class AnalysisContentProvider implements ITreeContentProvider {
@Override
public void dispose() {
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof AnalysisContextData) {
AnalysisContextData contentData = (AnalysisContextData) parentElement;
return contentData.statistics.getCacheRows();
}
return null;
}
@Override
public Object[] getElements(Object inputElement) {
synchronized (contextsLock) {
if (contexts == null) {
return ArrayUtils.EMPTY_OBJECT_ARRAY;
}
return contexts.toArray(new AnalysisContextData[contexts.size()]);
}
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return element instanceof AnalysisContextData;
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private static class AnalysisContextData {
private final String name;
private final InternalAnalysisContext context;
private final int maxCacheSize;
private final AnalysisContextStatistics statistics;
private final ContextWorkerState workerState;
private int errorCount;
private int flushedCount;
private int inProcessCount;
private int invalidCount;
private int validCount;
private Source[] sources;
private AnalysisException[] exceptions;
public AnalysisContextData(String name, InternalAnalysisContext context,
ContextWorkerState workerState) {
this.name = name;
this.context = context;
this.maxCacheSize = context.getAnalysisOptions().getCacheSize();
this.statistics = context.getStatistics();
this.workerState = workerState;
for (CacheRow row : statistics.getCacheRows()) {
errorCount += row.getErrorCount();
flushedCount += row.getFlushedCount();
inProcessCount += row.getInProcessCount();
invalidCount += row.getInvalidCount();
validCount += row.getValidCount();
}
this.sources = statistics.getSources();
this.exceptions = statistics.getExceptions();
}
@Override
public boolean equals(Object obj) {
return obj instanceof AnalysisContextData && ((AnalysisContextData) obj).name.equals(name);
}
public InternalAnalysisContext getContext() {
return context;
}
public int getErrorCount() {
return errorCount;
}
public int getFlushedCount() {
return flushedCount;
}
public int getInProcessCount() {
return inProcessCount;
}
public int getInvalidCount() {
return invalidCount;
}
public PartitionData[] getPartitionData() {
return statistics.getPartitionData();
}
public Source[] getSources() {
return sources;
}
public int getValidCount() {
return validCount;
}
@Override
public int hashCode() {
return name.hashCode();
}
}
private static enum ContextWorkerState {
NONE, IN_QUEUE, ACTIVE;
}
private static class LibraryDependencyCollector {
private final InternalAnalysisContext context;
private final Set<LibraryElement> visitedLibraries = new HashSet<LibraryElement>();
private final Set<String> dependencies = new TreeSet<String>();
LibraryDependencyCollector(InternalAnalysisContext context) {
this.context = context;
}
Set<String> collectDependencies() {
for (Source source : context.getLibrarySources()) {
addDependencies(context.getLibraryElement(source));
}
return dependencies;
}
private void addDependencies(LibraryElement libraryElement) {
if (visitedLibraries.add(libraryElement)) {
for (CompilationUnitElement cu : libraryElement.getUnits()) {
dependencies.add(cu.getSource().getFullName());
}
for (ImportElement importElement : libraryElement.getImports()) {
addDependencies(importElement.getImportedLibrary());
}
for (ExportElement exportElement : libraryElement.getExports()) {
addDependencies(exportElement.getExportedLibrary());
}
}
}
}
private static int COLUMN_WIDTH = 12;
private static void addContext(AnalysisWorker[] queueWorkers, AnalysisWorker activeWorker,
List<AnalysisContextData> contexts, String name, InternalAnalysisContext context) {
ContextWorkerState workerState = getContextWorkerState(queueWorkers, activeWorker, context);
contexts.add(new AnalysisContextData(name, context, workerState));
}
private static List<AnalysisContextData> getContexts() {
AnalysisWorker[] queueWorkers = AnalysisManager.getInstance().getQueueWorkers();
AnalysisWorker activeWorker = AnalysisManager.getInstance().getActiveWorker();
List<AnalysisContextData> contexts = Lists.newArrayList();
Set<AnalysisContext> visited = new HashSet<AnalysisContext>();
// TODO(scheglov) restore or remove for the new API
// AnalysisServer server = DartCore.getAnalysisServer();
// if (server instanceof InternalAnalysisServer) {
// Map<String, AnalysisContext> contextMap = ((InternalAnalysisServer) server).getContextMap();
// for (Entry<String, AnalysisContext> entry : contextMap.entrySet()) {
// String name = new Path(entry.getKey()).lastSegment();
// addContext(queueWorkers, activeWorker, contexts, name,
// (InternalAnalysisContext) entry.getValue());
// visited.add(entry.getValue());
// }
// }
//
// Show both analysis server and project manager contexts during this transition
//
if (!DartCoreDebug.ENABLE_ANALYSIS_SERVER) {
for (Project project : DartCore.getProjectManager().getProjects()) {
String projectName = project.getResource().getName();
// default context
AnalysisContext defaultContext = project.getDefaultContext();
if (visited.add(defaultContext)) {
addContext(queueWorkers, activeWorker, contexts, projectName,
(InternalAnalysisContext) defaultContext);
}
// separate Pub folders
for (PubFolder pubFolder : project.getPubFolders()) {
String pubFolderName = projectName + " - " + pubFolder.getResource().getName();
AnalysisContext context = pubFolder.getContext();
if (context != defaultContext && visited.add(context)) {
addContext(queueWorkers, activeWorker, contexts, pubFolderName,
(InternalAnalysisContext) context);
}
}
}
}
return contexts;
}
private static ContextWorkerState getContextWorkerState(AnalysisWorker[] queueWorkers,
AnalysisWorker activeWorker, AnalysisContext context) {
if (activeWorker != null && activeWorker.getContext() == context) {
return ContextWorkerState.ACTIVE;
} else {
for (AnalysisWorker worker : queueWorkers) {
if (worker.getContext() == context) {
return ContextWorkerState.IN_QUEUE;
}
}
}
return ContextWorkerState.NONE;
}
private TreeViewer viewer;
private long lastToggleTime = 0;
private boolean disposed = false;
private Font boldFont = null;
private Font italicFont = null;
private Color redColor = null;
private final Object contextsLock = new Object();
private List<AnalysisContextData> contexts;
@Override
public void createPartControl(Composite parent) {
viewer = new TreeViewer(parent, SWT.FULL_SELECTION);
viewer.getTree().setHeaderVisible(true);
viewer.getTree().setLinesVisible(true);
PixelConverter pixelConverter = new PixelConverter(parent);
{
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
TreeColumn column = viewerColumn.getColumn();
column.setText("Item");
column.setWidth(pixelConverter.convertWidthInCharsToPixels(50));
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public Font getFont(Object element) {
if (element instanceof AnalysisContextData) {
AnalysisContextData contextData = (AnalysisContextData) element;
if (contextData.workerState == ContextWorkerState.ACTIVE) {
return getBoldFont();
} else if (contextData.workerState == ContextWorkerState.IN_QUEUE) {
return getItalicFont();
}
}
return null;
}
@Override
public String getText(Object element) {
if (element instanceof AnalysisContextData) {
AnalysisContextData contextData = (AnalysisContextData) element;
StringBuilder builder = new StringBuilder();
builder.append(contextData.name);
builder.append(" [");
builder.append(contextData.maxCacheSize);
PartitionData[] data = contextData.getPartitionData();
for (int i = 0; i < data.length; i++) {
if (i == 0) {
builder.append(" | ");
} else {
builder.append("; ");
}
builder.append(data[i].getAstCount());
builder.append(", ");
builder.append(data[i].getTotalCount());
}
builder.append("]");
return builder.toString();
}
if (element instanceof CacheRow) {
return ((CacheRow) element).getName();
}
return null;
}
@Override
public String getToolTipText(Object element) {
if (element instanceof AnalysisContextData) {
AnalysisContextData contextData = (AnalysisContextData) element;
StringBuilder builder = new StringBuilder();
builder.append(contextData.name);
builder.append(" [max cache size = ");
builder.append(contextData.maxCacheSize);
PartitionData[] data = contextData.getPartitionData();
for (int i = 0; i < data.length; i++) {
if (i == 0) {
builder.append(" | ");
} else {
builder.append("; ");
}
builder.append("ast count = ");
builder.append(data[i].getAstCount());
builder.append(", entry count = ");
builder.append(data[i].getTotalCount());
}
builder.append("]");
return builder.toString();
}
if (element instanceof CacheRow) {
return ((CacheRow) element).getName();
}
return null;
}
});
}
{
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
TreeColumn column = viewerColumn.getColumn();
column.setText("ERROR");
column.setWidth(pixelConverter.convertWidthInCharsToPixels(COLUMN_WIDTH));
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public Color getBackground(Object element) {
if (element instanceof AnalysisContextData) {
if (((AnalysisContextData) element).getErrorCount() > 0) {
return getRedColor();
}
} else if (element instanceof CacheRow) {
if (((CacheRow) element).getErrorCount() > 0) {
return getRedColor();
}
}
return null;
}
@Override
public String getText(Object element) {
if (element instanceof AnalysisContextData) {
return "" + ((AnalysisContextData) element).getErrorCount();
}
if (element instanceof CacheRow) {
return "" + ((CacheRow) element).getErrorCount();
}
return "";
}
});
}
{
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
TreeColumn column = viewerColumn.getColumn();
column.setText("FLUSHED");
column.setWidth(pixelConverter.convertWidthInCharsToPixels(COLUMN_WIDTH));
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof AnalysisContextData) {
return "" + ((AnalysisContextData) element).getFlushedCount();
}
if (element instanceof CacheRow) {
return "" + ((CacheRow) element).getFlushedCount();
}
return "";
}
});
}
{
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
TreeColumn column = viewerColumn.getColumn();
column.setText("IN_PROCESS");
column.setWidth(pixelConverter.convertWidthInCharsToPixels(COLUMN_WIDTH));
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof AnalysisContextData) {
return "" + ((AnalysisContextData) element).getInProcessCount();
}
if (element instanceof CacheRow) {
return "" + ((CacheRow) element).getInProcessCount();
}
return "";
}
});
}
{
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
TreeColumn column = viewerColumn.getColumn();
column.setText("INVALID");
column.setWidth(pixelConverter.convertWidthInCharsToPixels(COLUMN_WIDTH));
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public Color getBackground(Object element) {
if (element instanceof AnalysisContextData) {
AnalysisContextData contextData = (AnalysisContextData) element;
if (contextData.getInvalidCount() > 0
&& contextData.workerState == ContextWorkerState.NONE) {
return getRedColor();
}
}
return null;
}
@Override
public String getText(Object element) {
if (element instanceof AnalysisContextData) {
return "" + ((AnalysisContextData) element).getInvalidCount();
}
if (element instanceof CacheRow) {
return "" + ((CacheRow) element).getInvalidCount();
}
return "";
}
});
}
{
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
TreeColumn column = viewerColumn.getColumn();
column.setText("VALID");
column.setWidth(pixelConverter.convertWidthInCharsToPixels(COLUMN_WIDTH));
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof AnalysisContextData) {
return "" + ((AnalysisContextData) element).getValidCount();
}
if (element instanceof CacheRow) {
return "" + ((CacheRow) element).getValidCount();
}
return "";
}
});
}
viewer.setContentProvider(new AnalysisContentProvider());
viewer.setSorter(new ViewerSorter() {
@Override
@SuppressWarnings("unchecked")
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof AnalysisContextData && e2 instanceof AnalysisContextData) {
String name1 = ((AnalysisContextData) e1).name;
String name2 = ((AnalysisContextData) e2).name;
return getComparator().compare(name1, name2);
}
if (e1 instanceof CacheRow && e2 instanceof CacheRow) {
String name1 = ((CacheRow) e1).getName();
String name2 = ((CacheRow) e2).getName();
return getComparator().compare(name1, name2);
}
return 0;
}
});
Menu menu = new Menu(viewer.getTree());
MenuItem copySourcesItem = new MenuItem(menu, SWT.PUSH);
copySourcesItem.setText("Copy Sources");
copySourcesItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
ISelection selection = viewer.getSelection();
if (selection instanceof TreeSelection) {
AnalysisContextData data = (AnalysisContextData) ((TreeSelection) selection).getFirstElement();
copySources(data);
}
}
});
MenuItem copyDependenciesItem = new MenuItem(menu, SWT.PUSH);
copyDependenciesItem.setText("Copy Library Dependencies");
copyDependenciesItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
ISelection selection = viewer.getSelection();
if (selection instanceof TreeSelection) {
AnalysisContextData data = (AnalysisContextData) ((TreeSelection) selection).getFirstElement();
copyLibraryDependencies(data);
}
}
});
new MenuItem(menu, SWT.SEPARATOR);
MenuItem copyExceptionsItem = new MenuItem(menu, SWT.PUSH);
copyExceptionsItem.setText("Copy All Exceptions");
copyExceptionsItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
copyExceptions();
}
});
MenuItem copyMemoryStatsItem = new MenuItem(menu, SWT.PUSH);
copyMemoryStatsItem.setText("Copy Memory Usage Statistics");
copyMemoryStatsItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
copyMemoryStats();
}
});
MenuItem copyPerformanceStatsItem = new MenuItem(menu, SWT.PUSH);
copyPerformanceStatsItem.setText("Copy Performance Statistics");
copyPerformanceStatsItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
copyPerformanceStats();
}
});
viewer.getTree().setMenu(menu);
viewer.setInput(this);
// There is a bug in the SWT on OS X.
// When we update a Tree when user toggle an item, this causes crash.
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=326311 - marked fixed, but actually is not.
viewer.addTreeListener(new ITreeViewerListener() {
@Override
public void treeCollapsed(TreeExpansionEvent event) {
lastToggleTime = System.currentTimeMillis();
}
@Override
public void treeExpanded(TreeExpansionEvent event) {
lastToggleTime = System.currentTimeMillis();
}
});
runUpdateLoop();
}
@Override
public void dispose() {
if (boldFont != null) {
boldFont.dispose();
boldFont = null;
}
if (italicFont != null) {
italicFont.dispose();
italicFont = null;
}
if (redColor != null) {
redColor.dispose();
redColor = null;
}
disposed = true;
super.dispose();
}
@Override
public void setFocus() {
}
private void appendPerfLine(StringBuilder buffer, String name, long time) {
buffer.append(name);
buffer.append(" ");
buffer.append(time);
buffer.append("\n");
}
private void copyExceptions() {
Clipboard clipboard = new Clipboard(viewer.getTree().getDisplay());
TextTransfer textTransfer = TextTransfer.getInstance();
clipboard.setContents(new Object[] {getExceptionsText()}, new Transfer[] {textTransfer});
}
private void copyLibraryDependencies(AnalysisContextData data) {
Clipboard clipboard = new Clipboard(viewer.getTree().getDisplay());
TextTransfer textTransfer = TextTransfer.getInstance();
clipboard.setContents(new Object[] {copyLibraryDependenciesText(data)},
new Transfer[] {textTransfer});
}
private String copyLibraryDependenciesText(AnalysisContextData data) {
InternalAnalysisContext context = data.getContext();
Set<String> paths = new LibraryDependencyCollector(context).collectDependencies();
return Joiner.on("\n").join(paths);
}
private void copyMemoryStats() {
Clipboard clipboard = new Clipboard(viewer.getTree().getDisplay());
TextTransfer textTransfer = TextTransfer.getInstance();
clipboard.setContents(new Object[] {getMemoryStatsText()}, new Transfer[] {textTransfer});
}
private void copyPerformanceStats() {
Clipboard clipboard = new Clipboard(viewer.getTree().getDisplay());
TextTransfer textTransfer = TextTransfer.getInstance();
clipboard.setContents(new Object[] {getPerformanceStatsText()}, new Transfer[] {textTransfer});
}
private void copySources(AnalysisContextData data) {
Clipboard clipboard = new Clipboard(viewer.getTree().getDisplay());
TextTransfer textTransfer = TextTransfer.getInstance();
clipboard.setContents(new Object[] {getSourcesText(data)}, new Transfer[] {textTransfer});
}
private Font getBoldFont() {
if (boldFont == null) {
Font defaultFont = viewer.getTree().getFont();
FontData defaultData = defaultFont.getFontData()[0];
FontData boldData = new FontData(defaultData.getName(), defaultData.getHeight(), SWT.BOLD);
boldFont = new Font(defaultFont.getDevice(), boldData);
}
return boldFont;
}
private String getExceptionsText() {
if (contexts == null) {
return "- no exceptions -";
}
PrintStringWriter writer = new PrintStringWriter();
boolean first = true;
for (AnalysisContextData data : contexts) {
for (AnalysisException exception : data.exceptions) {
if (first) {
first = false;
} else {
writer.println();
writer.println("----------------------------------------");
writer.println();
}
exception.printStackTrace(writer);
}
}
if (first) {
return "- no exceptions -";
}
return writer.toString();
}
private Font getItalicFont() {
if (italicFont == null) {
Font defaultFont = viewer.getTree().getFont();
FontData defaultData = defaultFont.getFontData()[0];
FontData boldData = new FontData(defaultData.getName(), defaultData.getHeight(), SWT.ITALIC);
italicFont = new Font(defaultFont.getDevice(), boldData);
}
return italicFont;
}
private String getMemoryStatsText() {
if (contexts == null || contexts.size() == 0) {
return "- no memory usage data -";
}
MemoryUsageData usageData = new MemoryUsageData();
for (AnalysisContextData data : contexts) {
usageData.addContext(data.getContext());
}
return usageData.getReport();
}
private String getPerformanceStatsText() {
StringBuilder buf = new StringBuilder();
buf.append("Time spent in each phase of analysis:\n");
appendPerfLine(buf, " io ", PerformanceStatistics.io.getResult());
appendPerfLine(buf, " scan ", PerformanceStatistics.scan.getResult());
appendPerfLine(buf, " parse ", PerformanceStatistics.parse.getResult());
appendPerfLine(buf, " resolve", PerformanceStatistics.resolve.getResult());
appendPerfLine(buf, " errors ", PerformanceStatistics.errors.getResult());
appendPerfLine(buf, " hints ", PerformanceStatistics.hints.getResult());
appendPerfLine(buf, " pub ", PerformanceStatistics.pubList.getResult());
buf.append("\n");
buf.append("Number of times data switched to VALID:\n");
// transitions
Map<DataDescriptor<?>, Map<CacheState, Integer>> transitionmap = SourceEntryImpl.transitionMap;
List<DataDescriptor<?>> descs = Lists.newArrayList(transitionmap.keySet());
Collections.sort(descs, new Comparator<DataDescriptor<?>>() {
@Override
public int compare(DataDescriptor<?> o1, DataDescriptor<?> o2) {
String name1 = o1.getName();
String name2 = o2.getName();
return name1.compareTo(name2);
}
});
for (DataDescriptor<?> desc : descs) {
buf.append(" ");
buf.append(desc);
buf.append("\n");
Map<CacheState, Integer> descMap = transitionmap.get(desc);
for (Entry<CacheState, Integer> entry2 : descMap.entrySet()) {
CacheState fromState = entry2.getKey();
int count = entry2.getValue();
buf.append(StringUtils.leftPad(Integer.toString(count), 15));
buf.append(" ");
buf.append(fromState.name());
buf.append("\n");
}
}
return buf.toString();
}
private Color getRedColor() {
if (redColor == null) {
Font defaultFont = viewer.getTree().getFont();
redColor = new Color(defaultFont.getDevice(), 255, 223, 223);
}
return redColor;
}
private String getSourcesText(AnalysisContextData data) {
Source[] sources = data.getSources();
int count = sources.length;
String[] paths = new String[count];
for (int i = 0; i < count; i++) {
paths[i] = sources[i].getFullName();
}
Arrays.sort(paths);
@SuppressWarnings("resource")
PrintStringWriter writer = new PrintStringWriter();
for (int i = 0; i < count; i++) {
writer.println(paths[i]);
}
return writer.toString();
}
private void refreshUI() {
Display display = Display.getDefault();
if (display == null || display.isDisposed()) {
return;
}
display.syncExec(new Runnable() {
@Override
public void run() {
if (viewer.getControl().isDisposed()) {
return;
}
viewer.refresh();
Index index = DartCore.getProjectManager().getIndex();
@SuppressWarnings("resource")
PrintStringWriter msg = new PrintStringWriter();
if (index instanceof IndexImpl) {
try {
Field field = IndexImpl.class.getDeclaredField("queue");
field.setAccessible(true);
OperationQueue queue = (OperationQueue) field.get(index);
msg.print("Index: queue size = " + queue.size() + "; statistics = "
+ index.getStatistics());
} catch (Exception exception) {
msg.print("Index: statistics = " + index.getStatistics());
}
} else {
msg.print("Index: statistics = " + index.getStatistics());
}
int totalAstSize = 0;
int totalMaxCacheSize = 0;
int totalCacheSize = 0;
int count = contexts.size();
for (int i = 0; i < count; i++) {
AnalysisContextData data = contexts.get(i);
PartitionData[] partitionDataArray = data.getPartitionData();
if (i == 0) {
PartitionData partitionData = partitionDataArray[0];
totalAstSize += partitionData.getAstCount();
totalCacheSize += partitionData.getTotalCount();
}
PartitionData partitionData = partitionDataArray[partitionDataArray.length - 1];
totalAstSize += partitionData.getAstCount();
totalMaxCacheSize += data.maxCacheSize;
totalCacheSize += partitionData.getTotalCount();
}
msg.print(" [ast count = ");
msg.print(totalAstSize);
msg.print(", max size = ");
msg.print(totalMaxCacheSize);
msg.print(", entry count = ");
msg.print(totalCacheSize);
msg.print("]");
setContentDescription(msg.toString());
}
});
}
private void runUpdateLoop() {
Thread thread = new Thread() {
@Override
public void run() {
updateLoop();
}
};
thread.setDaemon(true);
thread.setName("AnalysisView update thread");
thread.start();
}
private void updateLoop() {
while (!disposed) {
try {
synchronized (contextsLock) {
contexts = getContexts();
}
// wait while Tree is collapsing
while (System.currentTimeMillis() - lastToggleTime < 1000) {
Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
}
// do refresh
refreshUI();
Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
} catch (Throwable e) {
Uninterruptibles.sleepUninterruptibly(1000, TimeUnit.MILLISECONDS);
}
}
}
}