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. * Invokes an external tool to perform checks on a single file.
*/ */
public class ExternalToolInvoker { 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 String[] ENV = {};
private static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor(); private static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor();
@ -49,23 +50,25 @@ public class ExternalToolInvoker {
throws InvocationFailure, Throwable { throws InvocationFailure, Throwable {
Command command = commandBuilder.buildCommand(parameters, settings, argsSeparator); Command command = commandBuilder.buildCommand(parameters, settings, argsSeparator);
try { try {
launchCommand(command, parsers, parameters); launchCommand(command, parsers, parameters, settings);
} finally { } finally {
shutDown(parsers); shutDown(parsers);
} }
} }
private void launchCommand(Command command, IConsoleParser[] 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(); IProject project = parameters.getActualFile().getProject();
IConsole c = startConsole(project); IConsole c = startConsole(project, settings.getExternalToolName());
ConsoleOutputSniffer sniffer = ConsoleOutputSniffer sniffer =
new ConsoleOutputSniffer(c.getOutputStream(), c.getErrorStream(), parsers); new ConsoleOutputSniffer(c.getOutputStream(), c.getErrorStream(), parsers);
ICommandLauncher launcher = commandLauncher(project); ICommandLauncher launcher = commandLauncher(project);
Process p = launcher.execute(command.getPath(), command.getArgs(), ENV, Process p = launcher.execute(command.getPath(), command.getArgs(), ENV,
parameters.getWorkingDirectory(), NULL_PROGRESS_MONITOR); parameters.getWorkingDirectory(), NULL_PROGRESS_MONITOR);
if (p == null) { 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 { try {
p.getOutputStream().close(); p.getOutputStream().close();
@ -77,8 +80,8 @@ public class ExternalToolInvoker {
} }
} }
private IConsole startConsole(IProject project) { private IConsole startConsole(IProject project, String externalToolName) {
IConsole console = CCorePlugin.getDefault().getConsole(); IConsole console = CCorePlugin.getDefault().getConsole(null, DEFAULT_CONTEXT_MENU_ID, externalToolName, null);
console.start(project); console.start(project);
return console; 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; 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.IEditorReference;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IStartup; import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI; import org.eclipse.ui.PlatformUI;
@ -51,80 +38,10 @@ public class Startup implements IStartup {
public void run() { public void run() {
IWorkbenchWindow active = workbench.getActiveWorkbenchWindow(); IWorkbenchWindow active = workbench.getActiveWorkbenchWindow();
final IWorkbenchPage page = active.getActivePage(); final IWorkbenchPage page = active.getActivePage();
IPartListener2 partListener = new IPartListener2() { CodanPartListener partListener = new CodanPartListener();
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) {
}
};
page.addPartListener(partListener); page.addPartListener(partListener);
// Check current open editors. // Check current open editors.
IEditorReference[] editorReferences = page.getEditorReferences(); for (IEditorReference ref : page.getEditorReferences()) {
for (IEditorReference ref : editorReferences) {
partListener.partOpened(ref); partListener.partOpened(ref);
} }
} }

View file

@ -54,13 +54,17 @@ public class LaunchModesPropertyPage extends FieldEditorPreferencePage {
@Override @Override
protected void createFieldEditors() { protected void createFieldEditors() {
if (runInEditor) { 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())); addEditor(CheckerLaunchMode.RUN_ON_FILE_OPEN, CodanUIMessages.LaunchModesPropertyPage_RunOnFileOpen);
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FILE_SAVE.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFileSave, getFieldEditorParent())); addEditor(CheckerLaunchMode.RUN_ON_FILE_SAVE, CodanUIMessages.LaunchModesPropertyPage_RunOnFileSave);
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_INC_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild, getFieldEditorParent())); addEditor(CheckerLaunchMode.RUN_ON_INC_BUILD, CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild);
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild, getFieldEditorParent())); addEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD, CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild);
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_DEMAND.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnDemand, getFieldEditorParent())); addEditor(CheckerLaunchMode.RUN_ON_DEMAND, CodanUIMessages.LaunchModesPropertyPage_RunOnDemand);
}
private void addEditor(CheckerLaunchMode launchMode, String label) {
addField(new BooleanFieldEditor(launchMode.name(), label, getFieldEditorParent()));
} }
@Override @Override

View file

@ -1413,6 +1413,8 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
private final IndexerPreferenceListener fIndexerPreferenceListener; private final IndexerPreferenceListener fIndexerPreferenceListener;
private final ListenerList fPostSaveListeners;
private static final Set<String> angularIntroducers = new HashSet<String>(); private static final Set<String> angularIntroducers = new HashSet<String>();
static { static {
angularIntroducers.add("template"); //$NON-NLS-1$ angularIntroducers.add("template"); //$NON-NLS-1$
@ -1449,6 +1451,7 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this); fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this);
fIndexerPreferenceListener = new IndexerPreferenceListener(); 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);
}