mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
Bug 372551. Made "run on save" checker launch mode independent of
CodanBuilder. Introduced IPostSaveListener. Show external tool name in console (instead of "CDT Build"). Change-Id: Id2f84acdbdc433084fab1360f80ca3a30a4182ab Reviewed-on: https://git.eclipse.org/r/5760 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
parent
a601dc93f9
commit
a5e61b3f44
6 changed files with 200 additions and 97 deletions
|
@ -28,6 +28,7 @@ import org.eclipse.core.runtime.NullProgressMonitor;
|
|||
* Invokes an external tool to perform checks on a single file.
|
||||
*/
|
||||
public class ExternalToolInvoker {
|
||||
private static final String DEFAULT_CONTEXT_MENU_ID = "org.eclipse.cdt.ui.CDTBuildConsole"; //$NON-NLS-1$
|
||||
private static final String[] ENV = {};
|
||||
private static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor();
|
||||
|
||||
|
@ -49,23 +50,25 @@ public class ExternalToolInvoker {
|
|||
throws InvocationFailure, Throwable {
|
||||
Command command = commandBuilder.buildCommand(parameters, settings, argsSeparator);
|
||||
try {
|
||||
launchCommand(command, parsers, parameters);
|
||||
launchCommand(command, parsers, parameters, settings);
|
||||
} finally {
|
||||
shutDown(parsers);
|
||||
}
|
||||
}
|
||||
|
||||
private void launchCommand(Command command, IConsoleParser[] parsers,
|
||||
InvocationParameters parameters) throws InvocationFailure, CoreException {
|
||||
InvocationParameters parameters, ConfigurationSettings settings)
|
||||
throws InvocationFailure, CoreException {
|
||||
IProject project = parameters.getActualFile().getProject();
|
||||
IConsole c = startConsole(project);
|
||||
IConsole c = startConsole(project, settings.getExternalToolName());
|
||||
ConsoleOutputSniffer sniffer =
|
||||
new ConsoleOutputSniffer(c.getOutputStream(), c.getErrorStream(), parsers);
|
||||
ICommandLauncher launcher = commandLauncher(project);
|
||||
Process p = launcher.execute(command.getPath(), command.getArgs(), ENV,
|
||||
parameters.getWorkingDirectory(), NULL_PROGRESS_MONITOR);
|
||||
if (p == null) {
|
||||
throw new InvocationFailure("Unable to launch external tool. Cause unknown."); //$NON-NLS-1$
|
||||
String format = "Unable to launch external tool '%s'. Cause unknown."; //$NON-NLS-1$
|
||||
throw new InvocationFailure(String.format(format, settings.getExternalToolName()));
|
||||
}
|
||||
try {
|
||||
p.getOutputStream().close();
|
||||
|
@ -77,8 +80,8 @@ public class ExternalToolInvoker {
|
|||
}
|
||||
}
|
||||
|
||||
private IConsole startConsole(IProject project) {
|
||||
IConsole console = CCorePlugin.getDefault().getConsole();
|
||||
private IConsole startConsole(IProject project, String externalToolName) {
|
||||
IConsole console = CCorePlugin.getDefault().getConsole(null, DEFAULT_CONTEXT_MENU_ID, externalToolName, null);
|
||||
console.start(project);
|
||||
return console;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2012 Alena Laskavaia and others.
|
||||
* All rights reserved. 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
|
||||
*
|
||||
* Contributors:
|
||||
* Alena Laskavaia - initial API and implementation
|
||||
* Alex Ruiz (Google)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.internal.ui.cxx;
|
||||
|
||||
import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
|
||||
import org.eclipse.cdt.codan.internal.core.CodanRunner;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||
import org.eclipse.cdt.internal.ui.editor.IPostSaveListener;
|
||||
import org.eclipse.cdt.ui.ICEditor;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
import org.eclipse.ui.IPartListener2;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
import org.eclipse.ui.IWorkbenchPartReference;
|
||||
|
||||
/**
|
||||
* Enables Codan's "run as you type", "run on file save" and "run on file open" launch modes.
|
||||
*/
|
||||
class CodanPartListener implements IPartListener2 {
|
||||
private CodanCReconciler reconciler;
|
||||
private IPostSaveListener postSaveListener;
|
||||
|
||||
@Override
|
||||
public void partActivated(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partDeactivated(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partOpened(IWorkbenchPartReference partRef) {
|
||||
IWorkbenchPart part = partRef.getPart(false);
|
||||
if (isCEditor(part)) {
|
||||
CEditor editor = (CEditor) part;
|
||||
if (reconciler == null) {
|
||||
reconciler = new CodanCReconciler();
|
||||
}
|
||||
reconciler.install(editor);
|
||||
if (postSaveListener == null) {
|
||||
postSaveListener = new IPostSaveListener() {
|
||||
@Override
|
||||
public void saved(ITranslationUnit translationUnit, IProgressMonitor monitor) {
|
||||
processResource(translationUnit.getResource(), CheckerLaunchMode.RUN_ON_FILE_SAVE);
|
||||
}
|
||||
};
|
||||
}
|
||||
editor.addPostSaveListener(postSaveListener);
|
||||
IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
|
||||
processResource(resource, CheckerLaunchMode.RUN_ON_FILE_OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
private void processResource(final IResource resource, final CheckerLaunchMode launchMode) {
|
||||
if (resource != null) {
|
||||
Job job = new Job(NLS.bind(Messages.Startup_AnalyzingFile, resource.getName())) {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
CodanRunner.processResource(resource, launchMode, monitor);
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
job.setRule(resource);
|
||||
job.setSystem(true);
|
||||
job.schedule();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partHidden(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partVisible(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partClosed(IWorkbenchPartReference partRef) {
|
||||
IWorkbenchPart part = partRef.getPart(false);
|
||||
if (reconciler != null && isCEditor(part)) {
|
||||
reconciler.uninstall((CEditor) part);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCEditor(IWorkbenchPart part) {
|
||||
// We need to be very careful since this code may be executed in an environment where CDT is
|
||||
// installed, but is not actively used.
|
||||
// By checking for ICEditor first we avoid loading CEditor class if the part is not a C/C++
|
||||
// editor. Loading of CEditor class can be very expensive since it triggers loading of many
|
||||
// other classes.
|
||||
return part instanceof ICEditor && part instanceof CEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partBroughtToTop(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partInputChanged(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
}
|
|
@ -12,23 +12,10 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.internal.ui.cxx;
|
||||
|
||||
import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
|
||||
import org.eclipse.cdt.codan.internal.core.CodanRunner;
|
||||
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||
import org.eclipse.cdt.ui.ICEditor;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
import org.eclipse.ui.IEditorReference;
|
||||
import org.eclipse.ui.IPartListener2;
|
||||
import org.eclipse.ui.IStartup;
|
||||
import org.eclipse.ui.IWorkbench;
|
||||
import org.eclipse.ui.IWorkbenchPage;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
import org.eclipse.ui.IWorkbenchPartReference;
|
||||
import org.eclipse.ui.IWorkbenchWindow;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
|
||||
|
@ -51,80 +38,10 @@ public class Startup implements IStartup {
|
|||
public void run() {
|
||||
IWorkbenchWindow active = workbench.getActiveWorkbenchWindow();
|
||||
final IWorkbenchPage page = active.getActivePage();
|
||||
IPartListener2 partListener = new IPartListener2() {
|
||||
CodanCReconciler reconciler;
|
||||
|
||||
@Override
|
||||
public void partActivated(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partDeactivated(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partOpened(IWorkbenchPartReference partRef) {
|
||||
IWorkbenchPart part = partRef.getPart(false);
|
||||
// We need to be very careful since this code may be executed in
|
||||
// an invironement where CDT is installed, but is not actively used.
|
||||
// By checking for ICEditor first we avoid loading CEditor class if
|
||||
// the part is not a C/C++ editor. Loading of CEditor class can be very
|
||||
// expensive since it triggers loading of many other classes.
|
||||
if (part instanceof ICEditor && part instanceof CEditor) {
|
||||
CEditor editor = (CEditor) part;
|
||||
if (reconciler == null) {
|
||||
reconciler = new CodanCReconciler();
|
||||
}
|
||||
reconciler.install(editor);
|
||||
IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
|
||||
if (resource != null) {
|
||||
processResource(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processResource(final IResource resource) {
|
||||
Job job = new Job(NLS.bind(Messages.Startup_AnalyzingFile, resource.getName())) {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
CodanRunner.processResource(resource, CheckerLaunchMode.RUN_ON_FILE_OPEN, monitor);
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
job.setRule(resource);
|
||||
job.setSystem(true);
|
||||
job.schedule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partHidden(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partVisible(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partClosed(IWorkbenchPartReference partRef) {
|
||||
IWorkbenchPart part = partRef.getPart(false);
|
||||
if (reconciler != null && part instanceof ICEditor && part instanceof CEditor) {
|
||||
reconciler.uninstall((CEditor) part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partBroughtToTop(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partInputChanged(IWorkbenchPartReference partRef) {
|
||||
}
|
||||
};
|
||||
|
||||
CodanPartListener partListener = new CodanPartListener();
|
||||
page.addPartListener(partListener);
|
||||
// Check current open editors.
|
||||
IEditorReference[] editorReferences = page.getEditorReferences();
|
||||
for (IEditorReference ref : editorReferences) {
|
||||
for (IEditorReference ref : page.getEditorReferences()) {
|
||||
partListener.partOpened(ref);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,13 +54,17 @@ public class LaunchModesPropertyPage extends FieldEditorPreferencePage {
|
|||
@Override
|
||||
protected void createFieldEditors() {
|
||||
if (runInEditor) {
|
||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_AS_YOU_TYPE.name(), CodanUIMessages.LaunchModesPropertyPage_RunAsYouType, getFieldEditorParent()));
|
||||
addEditor(CheckerLaunchMode.RUN_AS_YOU_TYPE, CodanUIMessages.LaunchModesPropertyPage_RunAsYouType);
|
||||
}
|
||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FILE_OPEN.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFileOpen, getFieldEditorParent()));
|
||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FILE_SAVE.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFileSave, getFieldEditorParent()));
|
||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_INC_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild, getFieldEditorParent()));
|
||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild, getFieldEditorParent()));
|
||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_DEMAND.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnDemand, getFieldEditorParent()));
|
||||
addEditor(CheckerLaunchMode.RUN_ON_FILE_OPEN, CodanUIMessages.LaunchModesPropertyPage_RunOnFileOpen);
|
||||
addEditor(CheckerLaunchMode.RUN_ON_FILE_SAVE, CodanUIMessages.LaunchModesPropertyPage_RunOnFileSave);
|
||||
addEditor(CheckerLaunchMode.RUN_ON_INC_BUILD, CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild);
|
||||
addEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD, CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild);
|
||||
addEditor(CheckerLaunchMode.RUN_ON_DEMAND, CodanUIMessages.LaunchModesPropertyPage_RunOnDemand);
|
||||
}
|
||||
|
||||
private void addEditor(CheckerLaunchMode launchMode, String label) {
|
||||
addField(new BooleanFieldEditor(launchMode.name(), label, getFieldEditorParent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1413,6 +1413,8 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
|||
|
||||
private final IndexerPreferenceListener fIndexerPreferenceListener;
|
||||
|
||||
private final ListenerList fPostSaveListeners;
|
||||
|
||||
private static final Set<String> angularIntroducers = new HashSet<String>();
|
||||
static {
|
||||
angularIntroducers.add("template"); //$NON-NLS-1$
|
||||
|
@ -1449,6 +1451,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
|||
|
||||
fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this);
|
||||
fIndexerPreferenceListener = new IndexerPreferenceListener();
|
||||
fPostSaveListeners = new ListenerList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3766,4 +3769,29 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
|||
}});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void editorSaved() {
|
||||
super.editorSaved();
|
||||
ITranslationUnit translationUnit = getInputCElement().getOriginalElement();
|
||||
if (translationUnit != null) {
|
||||
for (Object listener : fPostSaveListeners.getListeners()) {
|
||||
((IPostSaveListener) listener).saved(translationUnit, getProgressMonitor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.4
|
||||
*/
|
||||
public void addPostSaveListener(IPostSaveListener listener) {
|
||||
fPostSaveListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.4
|
||||
*/
|
||||
public void removePostSaveListener(IPostSaveListener listener) {
|
||||
fPostSaveListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Google, Inc and others.
|
||||
* All rights reserved. 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
|
||||
*
|
||||
* Contributors:
|
||||
* Alex Ruiz (Google) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.editor;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
|
||||
/**
|
||||
* Listener that is informed when a translation unit is saved.
|
||||
* <p>
|
||||
* The difference between this interface and JDT's {@code IPostSaveListener} is that CDT does not
|
||||
* allow post-save listeners to make changes to the saved file.
|
||||
* </p>
|
||||
*
|
||||
* @since 5.4
|
||||
*/
|
||||
public interface IPostSaveListener {
|
||||
/**
|
||||
* Informs this post-save listener that the given translation unit has been saved. The listener
|
||||
* should <strong>not</strong> modify the given translation unit.
|
||||
*
|
||||
* @param translationUnit the translation unit which was saved
|
||||
* @param monitor the progress monitor for reporting progress
|
||||
*/
|
||||
void saved(ITranslationUnit translationUnit, IProgressMonitor monitor);
|
||||
}
|
Loading…
Add table
Reference in a new issue