/**
* Copyright (c) 2009-2010 MATSUFUJI Hideharu <matsufuji2008@gmail.com>,
* 2010-2014 KUBO Atsuhiro <kubo@iteman.jp>,
* All rights reserved.
*
* This file is part of MakeGood.
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package com.piece_framework.makegood.ui.views;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;
import com.piece_framework.makegood.core.TestResultsLayout;
import com.piece_framework.makegood.core.result.Result;
import com.piece_framework.makegood.core.result.TestCaseResult;
import com.piece_framework.makegood.core.result.TestSuiteResult;
import com.piece_framework.makegood.core.run.Failures;
import com.piece_framework.makegood.launch.CommandLineBuilder;
import com.piece_framework.makegood.launch.MakeGoodLaunch;
import com.piece_framework.makegood.launch.TestLifecycle;
import com.piece_framework.makegood.ui.Activator;
import com.piece_framework.makegood.ui.MakeGoodContext;
import com.piece_framework.makegood.ui.MakeGoodStatus;
import com.piece_framework.makegood.ui.MakeGoodStatusChangeListener;
import com.piece_framework.makegood.ui.Messages;
import com.piece_framework.makegood.ui.TestResultsLayoutChangeListener;
import com.piece_framework.makegood.ui.actions.ConfigureContinuousTestingAction;
import com.piece_framework.makegood.ui.actions.MoveToNextFailureAction;
import com.piece_framework.makegood.ui.actions.MoveToPreviousFailureAction;
import com.piece_framework.makegood.ui.actions.RerunFailedTestsAction;
import com.piece_framework.makegood.ui.actions.RerunTestAction;
import com.piece_framework.makegood.ui.actions.RunAllTestsAction;
import com.piece_framework.makegood.ui.actions.StopTestRunAction;
import com.piece_framework.makegood.ui.actions.ToggleDebugTestAction;
import com.piece_framework.makegood.ui.actions.ToggleShowOnlyFailuresAction;
import com.piece_framework.makegood.ui.actions.ToggleStopOnFailureAction;
import com.piece_framework.makegood.ui.widgets.ActiveText;
import com.piece_framework.makegood.ui.widgets.ActiveTextListener;
import com.piece_framework.makegood.ui.widgets.ExternalFileWithLineRange;
import com.piece_framework.makegood.ui.widgets.FileWithLineRange;
import com.piece_framework.makegood.ui.widgets.InternalFileWithLineRange;
import com.piece_framework.makegood.ui.widgets.MakeGoodColor;
import com.piece_framework.makegood.ui.widgets.ProgressBar;
public class ResultView extends ViewPart implements TestResultsLayoutChangeListener {
public static final String VIEW_ID = "com.piece_framework.makegood.ui.views.resultView"; //$NON-NLS-1$
/**
* @since 2.5.0
*/
public static boolean showOnlyFailures = false;
private static final String CONTEXT_ID = "com.piece_framework.makegood.ui.contexts.resultView"; //$NON-NLS-1$
private ProgressBar progressBar;
private CLabel testCountLabel;
private CountLabel passCountLabel;
private CountLabel failureCountLabel;
private CountLabel errorCountLabel;
private TreeViewer resultTreeViewer;
private CLabel processTimeAverageLabel;
private ElapsedTimer elapsedTimer;
private IAction moveToPreviousFailureAction;
private IAction moveToNextFailureAction;
private IAction stopTestAction;
/**
* @since 2.1.0
*/
private IAction rerunFailedTestsAction;
private IAction rerunTestAction;
private IAction runAllTestsAction;
private FailureTrace failureTrace;
private CLabel elapsedTimeLabel;
private CLabel processTimeLabel;
private boolean actionsInitialized = false;
private ResultViewPartListener partListener = new ResultViewPartListener();
private EditorOpener editorOpener = new EditorOpener();
private ViewerFilter failureViewFilter = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (!(element instanceof Result)) return false;
Result result = (Result) element;
return result.hasFailures() || result.hasErrors();
}
};
/**
* @since 1.3.0
*/
private TestLifecycle testLifecycle;
/**
* @since 1.6.0
*/
private StatusArea statusArea;
/**
* @since 1.8.0
*/
private AdditionalInformation additionalInformation = new AdditionalInformation();
/**
* @since 1.9.0
*/
private CLabel endTimeLabel;
/**
* @since 2.5.0
*/
private Composite testResultsComposite;
@Override
public void createPartControl(final Composite parent) {
IContextService service = (IContextService) getSite().getService(IContextService.class);
service.activateContext(CONTEXT_ID);
parent.setLayout(adjustLayout(new GridLayout()));
// Row1: The Status Area
statusArea = createStatusArea(parent, SWT.NONE);
statusArea.setLayoutData(createHorizontalFillGridData());
statusArea.setLayout(adjustLayout(new GridLayout()));
// Row2: The Progress Bar and Watches
Composite progressBarAndWatches = new Composite(parent, SWT.NONE);
progressBarAndWatches.setLayoutData(createHorizontalFillGridData());
progressBarAndWatches.setLayout(adjustLayout(new GridLayout(5, true)));
Composite progress = new Composite(progressBarAndWatches, SWT.NONE);
GridData progressGridData = createHorizontalFillGridData();
progressGridData.horizontalSpan = 2;
progress.setLayoutData(progressGridData);
progress.setLayout(adjustLayout(new GridLayout()));
Composite progressBarBorder = new Composite(progress, SWT.NONE);
progressBarBorder.setLayoutData(createHorizontalFillGridData());
GridLayout progressBarBorderLayout = new GridLayout();
progressBarBorderLayout.marginWidth = 2;
progressBarBorderLayout.marginHeight = 2;
progressBarBorderLayout.horizontalSpacing = 2;
progressBarBorderLayout.verticalSpacing = 2;
progressBarBorder.setLayout(progressBarBorderLayout);
progressBar = new ProgressBar(progressBarBorder);
progressBar.setLayoutData(createHorizontalFillGridData());
progressBar.setLayout(adjustLayout(new GridLayout()));
processTimeAverageLabel = new CLabel(progressBarAndWatches, SWT.LEFT);
processTimeAverageLabel.setLayoutData(createHorizontalFillGridData());
processTimeLabel = new CLabel(progressBarAndWatches, SWT.LEFT);
processTimeLabel.setLayoutData(createHorizontalFillGridData());
elapsedTimeLabel = new CLabel(progressBarAndWatches, SWT.LEFT);
elapsedTimeLabel.setLayoutData(createHorizontalFillGridData());
// Row3: The Counters
Composite counter = new Composite(parent, SWT.NONE);
counter.setLayoutData(createHorizontalFillGridData());
counter.setLayout(adjustLayout(new GridLayout(5, true)));
testCountLabel = new CLabel(counter, SWT.LEFT);
testCountLabel.setLayoutData(createHorizontalFillGridData());
passCountLabel = new CountLabel(
counter,
SWT.LEFT,
Messages.MakeGoodView_passesLabel,
Activator.getImageDescriptor("icons/pass_gray.gif").createImage() //$NON-NLS-1$
);
failureCountLabel = new CountLabel(
counter,
SWT.LEFT,
Messages.MakeGoodView_failuresLabel,
Activator.getImageDescriptor("icons/failure_gray.gif").createImage() //$NON-NLS-1$
);
errorCountLabel = new CountLabel(
counter,
SWT.LEFT,
Messages.MakeGoodView_errorsLabel,
Activator.getImageDescriptor("icons/error_gray.gif").createImage() //$NON-NLS-1$
);
endTimeLabel = new CLabel(counter, SWT.LEFT);
endTimeLabel.setLayoutData(createHorizontalFillGridData());
// Row4: The Test Results
testResultsComposite = createTestResultsComposite(parent, SWT.NONE, MakeGoodContext.getInstance().getTestResultsLayout());
IViewSite site = getViewSite();
site.getPage().addPartListener(partListener);
MakeGoodContext.getInstance().addStatusChangeListener(statusArea);
MakeGoodContext.getInstance().addTestResultsLayoutChangeListener(this);
clear();
testLifecycle = TestLifecycle.getInstance();
if (testLifecycle != null) {
if (testLifecycle.getProgress().isStopped()) {
markAsStopped();
} else if (testLifecycle.getProgress().hasFailures()) {
markAsFailed();
}
setTreeInput(testLifecycle.getProgress().getResult());
filterResults();
}
elapsedTimer = new ElapsedTimer(200);
}
@Override
public void setFocus() {
resultTreeViewer.getTree().setFocus();
}
private void clear() {
progressBar.clear();
processTimeAverageLabel.setText(
TimeFormatter.format(0)
+ "/" + //$NON-NLS-1$
Messages.MakeGoodView_averageTest
);
elapsedTimeLabel.setText(
Messages.MakeGoodView_realTime +
": " + //$NON-NLS-1$
TimeFormatter.format(0)
);
processTimeLabel.setText(
Messages.MakeGoodView_testTime +
": " + //$NON-NLS-1$
TimeFormatter.format(0)
);
endTimeLabel.setText(Messages.MakeGoodView_endTime + ":"); //$NON-NLS-1$
testCountLabel.setText(Messages.MakeGoodView_testsLabel + ": 0/0"); //$NON-NLS-1$
passCountLabel.clear();
failureCountLabel.clear();
errorCountLabel.clear();
resultTreeViewer.setInput(null);
additionalInformation.clearMessage();
setContentDescription(additionalInformation.toString());
}
private GridData createHorizontalFillGridData() {
GridData horizontalFillGrid = new GridData();
horizontalFillGrid.horizontalAlignment = GridData.FILL;
horizontalFillGrid.grabExcessHorizontalSpace = true;
return horizontalFillGrid;
}
private GridData createBothFillGridData() {
GridData bothFillGrid = new GridData();
bothFillGrid.horizontalAlignment = GridData.FILL;
bothFillGrid.verticalAlignment = GridData.FILL;
bothFillGrid.grabExcessHorizontalSpace = true;
bothFillGrid.grabExcessVerticalSpace = true;
return bothFillGrid;
}
private FailureTrace createFailureTrace(Composite parent, int style) {
FailureTrace failureTrace = new FailureTrace(parent, style);
failureTrace.setLayoutData(new GridData(GridData.FILL_BOTH));
failureTrace.setEditable(false);
failureTrace.addListener(new EditorOpenActiveTextListener());
return failureTrace;
}
/**
* @since 1.6.0
*/
private StatusArea createStatusArea(Composite parent, int style) {
StatusArea statusArea = new StatusArea(parent, style);
statusArea.setBackground(parent.getBackground());
statusArea.addListener(new PreferencesOpenActiveTextListener());
return statusArea;
}
public void moveToNextFailure() {
moveToPreviousOrNextFailure(Failures.FIND_NEXT);
}
public void moveToPreviousFailure() {
moveToPreviousOrNextFailure(Failures.FIND_PREVIOUS);
}
@Override
public void dispose() {
IViewSite site = getViewSite();
if (site != null) {
site.getPage().removePartListener(partListener);
}
MakeGoodContext.getInstance().removeTestResultsLayoutChangeListener(this);
MakeGoodContext.getInstance().removeStatusChangeListener(statusArea);
super.dispose();
}
public void filterResults() {
if (showOnlyFailures) {
resultTreeViewer.addFilter(failureViewFilter);
} else {
resultTreeViewer.removeFilter(failureViewFilter);
}
}
/**
* @since 1.3.0
*/
public boolean hasFailures() {
if (testLifecycle == null) return false;
return testLifecycle.getProgress().hasFailures();
}
/**
* @since 2.0.0
*/
public void switchToUnselectedTestResultsTab() {
if (testResultsComposite instanceof TabTestResultsComposite) {
((TabTestResultsComposite) testResultsComposite).switchToUnselectedTab();
}
}
void setTreeInput(TestSuiteResult result) {
resultTreeViewer.setInput(result);
}
void updateOnEndTestCase() {
if (testLifecycle.getProgress().hasFailures()) {
markAsFailed();
} else {
markAsPassed();
}
updateResult();
}
void updateOnStartTestCase(TestCaseResult testCase) {
updateTestCount();
resultTreeViewer.refresh();
}
void startTest(TestLifecycle testLifecycle) {
clear();
this.testLifecycle = testLifecycle;
elapsedTimer.schedule();
}
void endTest() {
updateResult();
updateEndTime();
TreeItem topItem = resultTreeViewer.getTree().getTopItem();
if (topItem != null) {
Result topResult = (Result) topItem.getData();
if (topResult != null) {
resultTreeViewer.setSelection(new StructuredSelection(topResult));
}
}
}
void markAsStopped() {
progressBar.markAsStopped();
}
void expandResultTreeToResult(Result result) {
resultTreeViewer.expandToLevel(result, TreeViewer.ALL_LEVELS);
}
private void markAsFailed() {
progressBar.markAsFailed();
if (moveToPreviousFailureAction != null) {
moveToPreviousFailureAction.setEnabled(true);
}
if (moveToNextFailureAction != null) {
moveToNextFailureAction.setEnabled(true);
}
}
/**
* @since 3.1.0
*/
private void markAsPassed() {
progressBar.markAsPassed();
}
private void initializeActions(IViewSite site) {
IToolBarManager manager = site.getActionBars().getToolBarManager();
ActionContributionItem showOnlyFailuresItem =
(ActionContributionItem) manager.find(ToggleShowOnlyFailuresAction.ACTION_ID);
if (showOnlyFailuresItem != null) {
showOnlyFailuresItem.getAction().setChecked(showOnlyFailures);
actionsInitialized = true;
}
ActionContributionItem previousFailureItem =
(ActionContributionItem) manager.find(MoveToPreviousFailureAction.ACTION_ID);
if (previousFailureItem != null) {
moveToPreviousFailureAction = previousFailureItem.getAction();
moveToPreviousFailureAction.setEnabled(hasFailures());
}
ActionContributionItem nextFailureItem =
(ActionContributionItem) manager.find(MoveToNextFailureAction.ACTION_ID);
if (nextFailureItem != null) {
moveToNextFailureAction = nextFailureItem.getAction();
moveToNextFailureAction.setEnabled(hasFailures());
}
ActionContributionItem stopOnFailureItem =
(ActionContributionItem) manager.find(ToggleStopOnFailureAction.ACTION_ID);
if (stopOnFailureItem != null) {
stopOnFailureItem.getAction().setChecked(CommandLineBuilder.stopOnFailure);
}
ActionContributionItem debugTestItem =
(ActionContributionItem) manager.find(ToggleDebugTestAction.ACTION_ID);
if (debugTestItem != null) {
debugTestItem.getAction().setChecked(MakeGoodContext.getInstance().isDebug());
}
ActionContributionItem stopTestItem =
(ActionContributionItem) manager.find(StopTestRunAction.ACTION_ID);
if (stopTestItem != null) {
stopTestAction = stopTestItem.getAction();
stopTestAction.setEnabled(MakeGoodLaunch.hasActiveLaunch());
}
ActionContributionItem rerunTestItem =
(ActionContributionItem) manager.find(RerunTestAction.ACTION_ID);
if (rerunTestItem != null) {
rerunTestAction = rerunTestItem.getAction();
rerunTestAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest());
}
ActionContributionItem rerunFailedTestsItem =
(ActionContributionItem) manager.find(RerunFailedTestsAction.ACTION_ID);
if (rerunFailedTestsItem != null) {
rerunFailedTestsAction = rerunFailedTestsItem.getAction();
rerunFailedTestsAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest());
}
ActionContributionItem runAllTestsItem =
(ActionContributionItem) manager.find(RunAllTestsAction.ACTION_ID);
if (runAllTestsItem != null) {
runAllTestsAction = runAllTestsItem.getAction();
runAllTestsAction.setEnabled(MakeGoodContext.getInstance().getActivePart().isAllTestsRunnable());
}
ActionContributionItem configureContinuousTestingItem =
(ActionContributionItem) manager.find(ConfigureContinuousTestingAction.ACTION_ID);
if (configureContinuousTestingItem != null) {
IAction configureContinuousTestingAction = configureContinuousTestingItem.getAction();
configureContinuousTestingAction.setImageDescriptor(
MakeGoodContext.getInstance().getContinuousTesting().isEnabled() ?
ConfigureContinuousTestingAction.IMAGE_DESCRIPTOR_ENABLED :
ConfigureContinuousTestingAction.IMAGE_DESCRIPTOR_DISABLED
);
}
}
private GridLayout adjustLayout(GridLayout layout) {
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
return layout;
}
private void moveToPreviousOrNextFailure(int direction) {
Result selectedResult = (Result) ((IStructuredSelection) resultTreeViewer.getSelection()).getFirstElement();
if (selectedResult == null) {
selectedResult = (Result) resultTreeViewer.getTree().getTopItem().getData();
}
TestCaseResult previousOrNextResult = testLifecycle.getFailures().find(selectedResult, direction);
if (previousOrNextResult == null) return;
resultTreeViewer.setSelection(new StructuredSelection(previousOrNextResult), true);
resultTreeViewer.expandToLevel(previousOrNextResult, TreeViewer.ALL_LEVELS);
try {
editorOpener.open(previousOrNextResult);
} catch (PartInitException e) {
Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, e.getMessage(), e));
}
}
private void updateResult() {
progressBar.update(testLifecycle.getProgress().calculateRate());
processTimeAverageLabel.setText(
TimeFormatter.format(testLifecycle.getProgress().calculateProcessTimeAverage()) +
"/" + //$NON-NLS-1$
Messages.MakeGoodView_averageTest
);
processTimeAverageLabel.getParent().layout();
processTimeLabel.setText(
Messages.MakeGoodView_testTime +
": " + //$NON-NLS-1$
TimeFormatter.format(testLifecycle.getProgress().getProcessTime())
);
passCountLabel.setCount(testLifecycle.getProgress().getPassCount());
failureCountLabel.setCount(testLifecycle.getProgress().getFailureCount());
errorCountLabel.setCount(testLifecycle.getProgress().getErrorCount());
resultTreeViewer.refresh();
}
private void updateElapsedTime() {
if (testLifecycle == null) return;
elapsedTimeLabel.setText(
Messages.MakeGoodView_realTime +
": " + //$NON-NLS-1$
TimeFormatter.format(testLifecycle.getProgress().getElapsedTime())
);
}
private void updateTestCount() {
if (testLifecycle == null) return;
testCountLabel.setText(
Messages.MakeGoodView_testsLabel +
": " + //$NON-NLS-1$
testLifecycle.getProgress().getCurrentTestCount() +
"/" + //$NON-NLS-1$
testLifecycle.getProgress().getAllTestCount()
);
}
private void update() {
IViewSite site = super.getViewSite();
if (site == null) return;
initializeActions(site);
if (testLifecycle != null) {
updateResult();
updateElapsedTime();
updateEndTime();
updateTestCount();
}
}
/**
* @since 1.9.0
*/
private void updateEndTime() {
if (testLifecycle != null && testLifecycle.getProgress().isRunning() == false && testLifecycle.getEndTime() != null) {
endTimeLabel.setText(
Messages.MakeGoodView_endTime +
": " + //$NON-NLS-1$
new SimpleDateFormat("HH:mm:ss").format(testLifecycle.getEndTime()) //$NON-NLS-1$
);
}
}
/**
* @since 2.5.0
*/
private Composite createTestResultsComposite(Composite parent, int style, TestResultsLayout testResultsLayout) {
if (TestResultsLayout.TAB.equals(testResultsLayout)) {
return createTabTestResultsComposite(parent, style);
} else if (TestResultsLayout.HORIZONTAL.equals(testResultsLayout)) {
return createHorizontalTestResultsComposite(parent, style);
} else {
return createTabTestResultsComposite(parent, style);
}
}
/**
* @since 2.5.0
*/
private Composite createTabTestResultsComposite(Composite parent, int style) {
CTabFolder testResultsComposite = new TabTestResultsComposite(parent, style);
testResultsComposite.setSimple(false);
testResultsComposite.setLayoutData(createBothFillGridData());
testResultsComposite.setLayout(adjustLayout(new GridLayout()));
return testResultsComposite;
}
/**
* @since 2.5.0
*/
private Composite createHorizontalTestResultsComposite(Composite parent, int style) {
SashForm testResultsComposite = new HorizontalResultsComposite(parent, style);
testResultsComposite.setLayoutData(createBothFillGridData());
testResultsComposite.setLayout(adjustLayout(new GridLayout(2, true)));
return testResultsComposite;
}
/**
* @since 2.5.0
*/
private TreeViewer createTestResultsTreeViewer(Tree resultTree) {
TreeViewer treeViewer = new TreeViewer(resultTree);
treeViewer.setContentProvider(new ResultTreeContentProvider());
treeViewer.setLabelProvider(new ResultTreeLabelProvider());
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
failureTrace.clearText();
if (!(event.getSelection() instanceof IStructuredSelection)) return;
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
Object element = selection.getFirstElement();
if (!(element instanceof TestCaseResult)) return;
TestCaseResult testCase = (TestCaseResult) element;
if (!testCase.isFixed()) return;
if (!testCase.hasFailures() && !testCase.hasErrors()) return;
failureTrace.setText(testCase.getFailureTrace());
}
});
treeViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
Object element = ((IStructuredSelection) event.getSelection()).getFirstElement();
if (element == null) return;
if (element instanceof Result) {
try {
editorOpener.open((Result) element);
} catch (PartInitException e) {
Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, e.getMessage(), e));
}
}
}
});
return treeViewer;
}
/**
* @since 2.5.0
*/
@Override
public void layoutChanged(TestResultsLayout testResultsLayout) {
Composite parent = testResultsComposite.getParent();
if (!testResultsComposite.isDisposed()) {
testResultsComposite.dispose();
}
testResultsComposite = createTestResultsComposite(parent, SWT.NONE, testResultsLayout);
testResultsComposite.getParent().layout();
testLifecycle = TestLifecycle.getInstance();
if (testLifecycle != null) {
setTreeInput(testLifecycle.getProgress().getResult());
}
}
private class CountLabel {
private CLabel label;
private String text;
public CountLabel(Composite parent, int style, String text, Image icon) {
label = new CLabel(parent, style);
label.setLayoutData(createHorizontalFillGridData());
label.setText(text);
label.setImage(icon);
this.text = text;
}
public void setCount(int count) {
label.setText(text + ": " + count); //$NON-NLS-1$
}
public void clear() {
setCount(0);
}
}
private class ElapsedTimer implements Runnable {
private int delay;
public ElapsedTimer(int delay) {
this.delay = delay;
}
public void schedule() {
elapsedTimeLabel.getDisplay().timerExec(delay, this);
}
@Override
public void run() {
if (!elapsedTimeLabel.isDisposed()) {
updateElapsedTime();
schedule();
}
}
}
private class FailureTrace extends ActiveText {
public FailureTrace(Composite parent, int style) {
super(parent, style);
}
@Override
public void clearText() {
super.clearText();
hideScrollBar();
}
/**
* @since 1.3.0
*/
@Override
public void setText(String text) {
super.setText(text);
showScrollBar();
}
/**
* @since 1.6.0
*/
private void showScrollBar() {
getVerticalBar().setVisible(true);
getHorizontalBar().setVisible(true);
}
/**
* @since 1.6.0
*/
private void hideScrollBar() {
getVerticalBar().setVisible(false);
getHorizontalBar().setVisible(false);
}
/**
* @since 1.6.0
*/
@Override
public void mouseDoubleClick(MouseEvent e) {
}
/**
* @since 1.6.0
*/
@Override
public void mouseDown(MouseEvent e) {
StyleRange style = findStyle(new Point(e.x, e.y));
if (style == null) return;
if (!(style instanceof FileWithLineRange)) return;
((FileWithLineRange) style).openEditor();
}
/**
* @since 1.6.0
*/
@Override
public void mouseUp(MouseEvent e) {
}
/**
* @since 1.6.0
*/
@Override
public void mouseMove(MouseEvent e) {
StyleRange style = findStyle(new Point(e.x, e.y));
if (style == null) {
setCursor(arrowCursor);
return;
}
if (style instanceof FileWithLineRange) {
setCursor(handCursor);
return;
}
setCursor(arrowCursor);
}
}
/**
* @since 1.6.0
*/
private class StatusArea extends ActiveText implements MakeGoodStatusChangeListener {
private static final String UIJOB_NAME = "MakeGood Status Update"; //$NON-NLS-1$
private MakeGoodStatus status;
public StatusArea(Composite parent, int style) {
super(parent, style);
}
/**
* @since 1.8.0
*/
public void updateAdditionalInformation() {
new UIJob(UIJOB_NAME) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isDisposed()) return Status.OK_STATUS;;
setContentDescription(additionalInformation.toString());
return Status.OK_STATUS;
}
}.schedule();
}
public void isFailure(final String message) {
new UIJob(UIJOB_NAME) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isDisposed()) return Status.OK_STATUS;;
if (actionsInitialized) {
runAllTestsAction.setEnabled(false);
rerunTestAction.setEnabled(false);
rerunFailedTestsAction.setEnabled(false);
}
setForeground(new Color(statusArea.getDisplay(), MakeGoodColor.FAILED));
setText(message);
return Status.OK_STATUS;
}
}.schedule();
}
public void runningTest() {
new UIJob(UIJOB_NAME) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isDisposed()) return Status.OK_STATUS;;
if (actionsInitialized) {
runAllTestsAction.setEnabled(false);
rerunTestAction.setEnabled(false);
rerunFailedTestsAction.setEnabled(false);
stopTestAction.setEnabled(true);
moveToPreviousFailureAction.setEnabled(false);
moveToNextFailureAction.setEnabled(false);
}
setForeground(statusArea.getParent().getForeground());
setText(Messages.MakeGoodView_Status_RunningTest);
return Status.OK_STATUS;
}
}.schedule();
}
public void waitingForTestRun() {
new UIJob(UIJOB_NAME) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isDisposed()) return Status.OK_STATUS;;
if (actionsInitialized) {
runAllTestsAction.setEnabled(MakeGoodContext.getInstance().getActivePart().isAllTestsRunnable());
rerunTestAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest());
rerunFailedTestsAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest());
stopTestAction.setEnabled(false);
}
setForeground(statusArea.getParent().getForeground());
setText(Messages.MakeGoodView_Status_WaitingForTestRun);
return Status.OK_STATUS;
}
}.schedule();
}
@Override
public void statusChanged(MakeGoodStatus status) {
this.status = status;
if (this.status.getProject() != null) {
additionalInformation.setProject(this.status.getProject());
}
if (status == MakeGoodStatus.TestsNotFound) {
additionalInformation.setMessage(Messages.MakeGoodView_Status_TestsNotFound);
} else if (status == MakeGoodStatus.RelatedTestsNotFound) {
additionalInformation.setMessage(Messages.MakeGoodView_Status_RelatedTestsNotFound);
} else if (status == MakeGoodStatus.TypesNotFound) {
additionalInformation.setMessage(Messages.MakeGoodView_Status_TypesNotFound);
} else if (status == MakeGoodStatus.TestTargetNotFound) {
additionalInformation.setMessage(Messages.MakeGoodView_Status_TestTargetNotFound);
}
updateAdditionalInformation();
switch (status) {
case NoProjectSelected:
isFailure(Messages.MakeGoodView_Status_NoProjectSelected);
break;
case ProjectNotFound:
isFailure(Messages.MakeGoodView_Status_ProjectNotFound);
break;
case ProjectNotOpen:
isFailure(Messages.MakeGoodView_Status_ProjectNotOpen);
break;
case NoTestableProjectSelected:
isFailure(Messages.MakeGoodView_Status_NoTestableProjectSelected);
break;
case NoPHPExecutablesDefined:
isFailure(Messages.MakeGoodView_Status_NoPHPExecutablesDefined);
break;
case SAPINotCLI:
isFailure(Messages.MakeGoodView_Status_SAPINotCLI);
break;
case MakeGoodNotConfigured:
isFailure(Messages.MakeGoodView_Status_MakeGoodNotConfigured);
break;
case TestingFrameworkNotAvailable:
isFailure(status.getReason() + " " + Messages.MakeGoodView_Status_TestingFrameworkNotAvailable); //$NON-NLS-1$
break;
case RunningTest:
runningTest();
break;
case WaitingForTestRun:
waitingForTestRun();
break;
default:
break;
}
}
@Override
public void mouseDoubleClick(MouseEvent e) {
}
@Override
public void mouseDown(MouseEvent e) {
if (status == null) return;
IProject project = status.getProject();
if (project == null) return;
if (!project.exists()) return;
StyleRange style = findStyle(new Point(e.x, e.y));
if (style == null) return;
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window == null) return;
IEclipsePreferences node = new ProjectScope(project).getNode("org.eclipse.php.debug.core.Debug_Process_Preferences"); //$NON-NLS-1$
if (node == null) return;
switch (status) {
case NoPHPExecutablesDefined:
case SAPINotCLI:
if (!node.getBoolean("org.eclipse.php.debug.core.use-project-settings", false)) { //$NON-NLS-1$
PreferencesUtil.createPreferenceDialogOn(
window.getShell(),
"org.eclipse.php.debug.ui.preferences.PhpDebugPreferencePage", //$NON-NLS-1$
null,
null
).open();
} else {
PreferencesUtil.createPropertyDialogOn(
window.getShell(),
project,
"org.eclipse.php.debug.ui.property.PhpDebugPreferencePage", //$NON-NLS-1$
null,
null
).open();
}
break;
case MakeGoodNotConfigured:
case TestingFrameworkNotAvailable:
PreferencesUtil.createPropertyDialogOn(
window.getShell(),
project,
"com.piece_framework.makegood.ui.propertyPages.makeGood", //$NON-NLS-1$
null,
null
).open();
break;
default:
break;
}
}
@Override
public void mouseUp(MouseEvent e) {
}
@Override
public void mouseMove(MouseEvent e) {
StyleRange style = findStyle(new Point(e.x, e.y));
if (style == null) {
setCursor(arrowCursor);
} else {
setCursor(handCursor);
}
}
}
private class ResultViewPartListener implements IPartListener2 {
@Override
public void partActivated(IWorkbenchPartReference partRef) {
if (!VIEW_ID.equals(partRef.getId())) {
IWorkbenchPart activePart = partRef.getPage().getActivePart();
if (activePart != null) {
MakeGoodContext.getInstance().getActivePart().update(activePart);
}
return;
}
update();
}
@Override
public void partBroughtToTop(IWorkbenchPartReference partRef) {}
@Override
public void partClosed(IWorkbenchPartReference partRef) {}
@Override
public void partDeactivated(IWorkbenchPartReference partRef) {}
@Override
public void partOpened(IWorkbenchPartReference partRef) {
if (!VIEW_ID.equals(partRef.getId())) return;
update();
}
@Override
public void partHidden(IWorkbenchPartReference partRef) {}
@Override
public void partVisible(IWorkbenchPartReference partRef) {
if (!VIEW_ID.equals(partRef.getId())) return;
update();
}
@Override
public void partInputChanged(IWorkbenchPartReference partRef) {}
}
private class ResultTreeContentProvider implements ITreeContentProvider {
@Override
public Object[] getChildren(Object parentElement) {
List<Result> children = new ArrayList<Result>(((Result) parentElement).getChildren());
Collections.reverse(children);
return children.toArray(new Result[ children.size() ]);
}
@Override
public Object getParent(Object element) {
return ((Result) element).getParent();
}
@Override
public boolean hasChildren(Object element) {
if (!(element instanceof TestSuiteResult)) return false;
return ((TestSuiteResult) element).hasChildren();
}
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private class ResultTreeLabelProvider extends LabelProvider {
private Image passIcon;
private Image errorIcon;
private Image failureIcon;
private Image inProgressIcon;
public ResultTreeLabelProvider() {
super();
passIcon = Activator.getImageDescriptor("icons/pass_white.gif").createImage(); //$NON-NLS-1$
errorIcon = Activator.getImageDescriptor("icons/error_white.gif").createImage(); //$NON-NLS-1$
failureIcon = Activator.getImageDescriptor("icons/failure_white.gif").createImage(); //$NON-NLS-1$
inProgressIcon = Activator.getImageDescriptor("icons/in_progress.gif").createImage(); //$NON-NLS-1$
}
@Override
public String getText(Object element) {
Result result = (Result) element;
return result.getName() + " (" + //$NON-NLS-1$
TimeFormatter.format(result.getTime()) +
")"; //$NON-NLS-1$
}
@Override
public Image getImage(Object element) {
Result result = (Result) element;
if (result.isFixed()) {
if (result.hasFailures()) {
return failureIcon;
} else if (result.hasErrors()) {
return errorIcon;
} else {
return passIcon;
}
} else {
return inProgressIcon;
}
}
}
private static class TimeFormatter {
private static String format(long nanoTime) {
double timeForFormat = 0.0d;
String unit = null;
if (nanoTime >= 1000000000) {
timeForFormat = nanoTime / 1000000000d;
unit = "s"; //$NON-NLS-1$
} else if (nanoTime < 1000000000 && nanoTime >= 1000){
timeForFormat = nanoTime / 1000000d;
unit = "ms"; //$NON-NLS-1$
} else if (nanoTime > 0){
return "< 0.001ms"; //$NON-NLS-1$
} else {
return "0.000ms"; //$NON-NLS-1$
}
return String.format("%.3f%s", timeForFormat, unit); //$NON-NLS-1$
}
}
private class EditorOpenActiveTextListener extends ActiveTextListener {
public EditorOpenActiveTextListener() {
super(Pattern.compile("^((?:/|[A-Z]:).+):(\\d+)$", Pattern.MULTILINE));
}
@Override
public void generateActiveText() {
Matcher matcher = pattern.matcher(text.getText());
while (matcher.find()) {
FileWithLineRange style;
IFile file =
ResourcesPlugin.getWorkspace()
.getRoot()
.getFileForLocation(new Path(matcher.group(1)));
if (file != null) {
InternalFileWithLineRange iStyle = new InternalFileWithLineRange();
iStyle.file = file;
iStyle.foreground = new Color(text.getDisplay(), MakeGoodColor.LINK_INTERNAL);
style = (FileWithLineRange) iStyle;
} else {
ExternalFileWithLineRange eStyle = new ExternalFileWithLineRange();
eStyle.fileStore =
EFS.getLocalFileSystem().getStore(new Path(matcher.group(1)));
eStyle.foreground = new Color(text.getDisplay(), MakeGoodColor.LINK_EXTERNAL);
style = (FileWithLineRange) eStyle;
}
style.start = matcher.start();
style.length = matcher.group().length();
style.line = Integer.valueOf(matcher.group(2));
this.text.addStyle(style);
}
}
}
/**
* @since 1.6.0
*/
private class PreferencesOpenActiveTextListener extends ActiveTextListener {
public PreferencesOpenActiveTextListener() {
super(Pattern.compile("(?:<a>)(.+?)(?:</a>)")); //$NON-NLS-1$
}
@Override
public void generateActiveText() {
Matcher matcher = pattern.matcher(text.getText());
while (matcher.find()) {
StyleRange style = new StyleRange();
style.underline = true;
style.start = matcher.start();
style.length = matcher.group(1).length();
text.replaceText(matcher.replaceFirst(matcher.group(1)));
text.addStyle(style);
}
}
}
/**
* @since 1.8.0
*/
private class AdditionalInformation {
private IProject project;
private String message;
public void setProject(IProject project) {
if (this.project != null && this.project != project) {
clearMessage();
}
this.project = project;
}
public void setMessage(String message) {
this.message = message;
}
public void clearMessage() {
setMessage(null);
}
@Override
public String toString() {
StringBuilder information = new StringBuilder();
if (project != null) {
information.append("[" + project.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
}
if (message != null && message.length() > 0) {
information.append(" "); //$NON-NLS-1$
information.append(message);
}
return information.toString();
}
}
/**
* @since 2.5.0
*/
private class TabTestResultsComposite extends CTabFolder {
private CTabItem testResultsTreeTabItem;
private CTabItem failureTraceTabItem;
public TabTestResultsComposite(Composite parent, int style) {
super(parent, style);
testResultsTreeTabItem = new CTabItem(this, SWT.NONE);
testResultsTreeTabItem.setText(Messages.MakeGoodView_testResultsLabel);
testResultsTreeTabItem.setImage(Activator.getImageDescriptor("icons/test_results.gif").createImage()); //$NON-NLS-1$
setSelection(testResultsTreeTabItem);
Tree testResultsTree = new Tree(this, SWT.BORDER);
testResultsTree.setLayoutData(createBothFillGridData());
testResultsTreeTabItem.setControl(testResultsTree);
resultTreeViewer = createTestResultsTreeViewer(testResultsTree);
failureTraceTabItem = new CTabItem(this, SWT.NONE);
failureTraceTabItem.setText(Messages.MakeGoodView_failureTraceLabel);
failureTraceTabItem.setImage(Activator.getImageDescriptor("icons/failure_trace.gif").createImage()); //$NON-NLS-1$
failureTrace = createFailureTrace(this, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
failureTraceTabItem.setControl(failureTrace);
}
public void switchToUnselectedTab() {
if (getSelection() == testResultsTreeTabItem) {
setSelection(failureTraceTabItem);
} else if (getSelection() == failureTraceTabItem) {
setSelection(testResultsTreeTabItem);
}
}
}
/**
* @since 2.5.0
*/
private class HorizontalResultsComposite extends SashForm {
public HorizontalResultsComposite(Composite parent, int style) {
super(parent, style);
Composite testResultsTreeComposite = new Composite(this, SWT.NONE);
testResultsTreeComposite.setLayoutData(createHorizontalFillGridData());
testResultsTreeComposite.setLayout(adjustLayout(new GridLayout(1, true)));
Tree testResultsTree = new Tree(testResultsTreeComposite, SWT.BORDER);
testResultsTree.setLayoutData(createBothFillGridData());
resultTreeViewer = createTestResultsTreeViewer(testResultsTree);
testResultsTree.setLayoutData(createBothFillGridData());
Composite failureTraceComposite = new Composite(this, SWT.NONE);
failureTraceComposite.setLayoutData(createHorizontalFillGridData());
failureTraceComposite.setLayout(adjustLayout(new GridLayout(1, true)));
CLabel failureTraceLabel = new CLabel(failureTraceComposite, SWT.LEFT);
failureTraceLabel.setText(Messages.MakeGoodView_failureTraceLabel);
failureTraceLabel.setImage(Activator.getImageDescriptor("icons/failure_trace.gif").createImage()); //$NON-NLS-1$
failureTrace = createFailureTrace(failureTraceComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
}
}
}