1
0
Fork 0
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:
Alex Ruiz 2012-04-30 22:51:58 -07:00 committed by Sergey Prigogin
parent a601dc93f9
commit a5e61b3f44
6 changed files with 200 additions and 97 deletions

View file

@ -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;
}

View file

@ -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) {
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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);
}