/*
* SonarLint for Eclipse
* Copyright (C) 2015-2017 SonarSource SA
* sonarlint@sonarsource.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonarlint.eclipse.ui.internal.views.issues;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.sonarlint.eclipse.core.SonarLintLogger;
import org.sonarlint.eclipse.core.internal.jobs.AnalyzeChangedFilesJob;
import org.sonarlint.eclipse.core.internal.resources.DefaultSonarLintProjectAdapter;
import org.sonarlint.eclipse.core.internal.resources.ProjectsProviderUtils;
import org.sonarlint.eclipse.core.resource.ISonarLintFile;
import org.sonarlint.eclipse.core.resource.ISonarLintProject;
import org.sonarlint.eclipse.ui.internal.SonarLintUiPlugin;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
public class ChangeSetIssuesView extends MarkerViewWithBottomPanel {
public static final String ID = SonarLintUiPlugin.PLUGIN_ID + ".views.issues.ChangeSetIssuesView";
private static LocalDateTime lastRefresh;
private static ChangeSetIssuesView instance;
private Label label;
private Button btnPrj;
private Composite btnPrjWrapper;
private Button btnAll;
private Composite bottom;
public ChangeSetIssuesView() {
super(SonarLintUiPlugin.PLUGIN_ID + ".views.issues.changeSetIssueMarkerGenerator");
instance = this;
}
@Override
public void dispose() {
super.dispose();
instance = null;
}
@Override
protected void populateBottomPanel(Composite bottom) {
this.bottom = bottom;
RowLayout bottomLayout = new RowLayout();
bottomLayout.center = true;
bottom.setLayout(bottomLayout);
GridData bottomLayoutData = new GridData(SWT.FILL, SWT.FILL, true, false);
bottom.setLayoutData(bottomLayoutData);
Label caption = new Label(bottom, SWT.NONE);
caption.setText("Run the analysis and find issues on the files in the SCM change set:");
btnPrjWrapper = new Composite(bottom, SWT.NONE);
// default values so it doesn't grab excess space
btnPrjWrapper.setLayoutData(new RowData());
btnPrjWrapper.setLayout(new FillLayout());
btnPrj = new Button(btnPrjWrapper, SWT.PUSH);
btnPrj.setText("Current project");
refreshBtnState();
btnPrj.addListener(SWT.Selection, e -> {
ISonarLintFile editedFile = SonarLintUiPlugin.findCurrentEditedFile();
if (editedFile != null) {
triggerAnalysis(asList(editedFile.getProject()));
}
});
btnAll = new Button(bottom, SWT.PUSH);
btnAll.setText("All projects");
btnAll.setToolTipText("Analyze all changed files in all projects");
btnAll.addListener(SWT.Selection, e -> triggerAnalysis(
ProjectsProviderUtils.allProjects().stream()
.filter(ISonarLintProject::isOpen)
.collect(toList())));
label = new Label(bottom, SWT.NONE);
refreshText();
}
private void refreshBtnState() {
ISonarLintFile editedFile = SonarLintUiPlugin.findCurrentEditedFile();
if (editedFile == null) {
btnPrjWrapper.setToolTipText("No editor opened or current file not analyzable");
btnPrj.setEnabled(false);
} else {
String msgNoScm;
ISonarLintProject project = editedFile.getProject();
if (project instanceof DefaultSonarLintProjectAdapter) {
DefaultSonarLintProjectAdapter slProject = (DefaultSonarLintProjectAdapter) project;
msgNoScm = slProject.getNoScmSupportCause();
} else {
msgNoScm = "SCM not supported on the current project";
}
if (msgNoScm != null) {
btnPrjWrapper.setToolTipText(msgNoScm);
btnPrj.setEnabled(false);
} else {
btnPrjWrapper.setToolTipText(project.getName());
btnPrj.setEnabled(true);
}
}
}
private void refreshText() {
if (lastRefresh != null) {
label.setText("Report generated on " + DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm").format(lastRefresh));
} else {
label.setText("");
}
}
public static void notifyEditorChanged() {
if (ChangeSetIssuesView.instance != null) {
instance.refreshBtnState();
instance.requestLayout();
}
}
public static void setRefreshTime(LocalDateTime now) {
ChangeSetIssuesView.lastRefresh = now;
if (ChangeSetIssuesView.instance != null) {
instance.refreshText();
instance.requestLayout();
}
}
private void requestLayout() {
// TODO replace by requestLayout() when supporting only Eclipse 4.6+
bottom.getShell().layout(new Control[] {instance.bottom}, SWT.DEFER);
}
public static void triggerAnalysis(Collection<ISonarLintProject> selectedProjects) {
// Disable button if view is visible
if (ChangeSetIssuesView.instance != null) {
ChangeSetIssuesView.instance.btnAll.setEnabled(false);
ChangeSetIssuesView.instance.btnPrj.setEnabled(false);
}
AnalyzeChangedFilesJob job = new AnalyzeChangedFilesJob(selectedProjects);
registerJobListener(job);
job.schedule();
}
private static void registerJobListener(Job job) {
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
Display.getDefault().asyncExec(() -> {
// Enable button if view is visible
if (ChangeSetIssuesView.instance != null) {
ChangeSetIssuesView.instance.btnAll.setEnabled(true);
ChangeSetIssuesView.instance.refreshBtnState();
}
if (Status.OK_STATUS == event.getResult()) {
// Display changeset issues view after analysis is completed
IWorkbenchWindow iw = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
try {
iw.getActivePage().showView(ChangeSetIssuesView.ID, null, IWorkbenchPage.VIEW_ACTIVATE);
ChangeSetIssuesView.setRefreshTime(LocalDateTime.now());
} catch (PartInitException e) {
SonarLintLogger.get().error("Unable to open ChangeSet Issues View", e);
}
}
});
}
});
}
}