diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF index 52a38b204ca..0a30ab5d08b 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF @@ -10,7 +10,9 @@ Require-Bundle: org.eclipse.ui, org.eclipse.jface.text;bundle-version="3.5.0", org.eclipse.ui.editors;bundle-version="3.5.0", org.eclipse.core.resources;bundle-version="3.5.0", - org.eclipse.cdt.codan.checkers;bundle-version="1.0.0" + org.eclipse.cdt.codan.checkers;bundle-version="1.0.0", + org.eclipse.cdt.ui;bundle-version="5.2.0", + org.eclipse.cdt.core;bundle-version="5.2.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-Vendor: Eclipse CDT diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml b/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml index 52cc0a79bf2..bee18e15b55 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml +++ b/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml @@ -1,6 +1,7 @@ + + + + + + + diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/schema/codanMarkerResolution.exsd b/codan/org.eclipse.cdt.codan.checkers.ui/schema/codanMarkerResolution.exsd new file mode 100644 index 00000000000..0c3f1e85cef --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui/schema/codanMarkerResolution.exsd @@ -0,0 +1,130 @@ + + + + + + + + + Extension point to plugin quick fix for codan markers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Contribute codan marker resolution + + + + + + + Class that implement IMarkerResolution that provides a fix for the given problem + + + + + + + + + + Problem id of the problem for which quick fix is defined + + + + + + + + + + If problem id is not enought to identity the fix messagePattern can be used to apply fix for given message + + + + + + + + + + + + since 1.0 + + + + + + + + + <extension + point="org.eclipse.cdt.codan.checkers.ui.codanMarkerResolution"> + <resolution + class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CatchByReferenceQuickFix" + problemId="org.eclipse.cdt.codan.internal.checkers.CatchByReference"> + </resolution> + </extension> + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/checkers/ui/AbstarctCodanCMarkerResolution.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/checkers/ui/AbstarctCodanCMarkerResolution.java new file mode 100644 index 00000000000..879eb8e3131 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/checkers/ui/AbstarctCodanCMarkerResolution.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2009 Alena Laskavaia + * 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 + *******************************************************************************/ +package org.eclipse.cdt.codan.checkers.ui; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IMarkerResolution; +import org.eclipse.ui.IMarkerResolution2; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Generic class for codan marker resolution (for quick fix). + * Use as a base class for codanMarkerResolution extension. + * To add specific icon and description client class should additionally + * implement {@link IMarkerResolution2} + */ +public abstract class AbstarctCodanCMarkerResolution implements + IMarkerResolution { + /** + * Get position offset from marker. If CHAR_START attribute is not set + * for marker, line and document would be used. + * @param marker + * @param doc + * @return + */ + public int getOffset(IMarker marker, IDocument doc) { + int charStart = marker.getAttribute(IMarker.CHAR_START, -1); + int position; + if (charStart > 0) { + position = charStart; + } else { + int line = marker.getAttribute(IMarker.LINE_NUMBER, -1) - 1; + try { + position = doc.getLineOffset(line); + } catch (BadLocationException e) { + return -1; + } + } + return position; + } + /** + * Runs this resolution. + * + * @param marker the marker to resolve + */ + public void run(IMarker marker) { + // See if there is an open editor on the file containing the marker + IWorkbenchWindow w = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow(); + if (w == null) { + return; + } + IWorkbenchPage page = w.getActivePage(); + if (page == null) { + return; + } + IFileEditorInput input = new FileEditorInput((IFile) marker + .getResource()); + IEditorPart editorPart = page.findEditor(input); + if (editorPart == null) { + // open an editor + try { + editorPart = IDE.openEditor(page, (IFile) marker.getResource(), + true); + } catch (PartInitException e) { + e.printStackTrace(); + } + } + if (editorPart == null) { + return; + } + if (editorPart instanceof ITextEditor) { + ITextEditor editor = (ITextEditor) editorPart; + IDocument doc = editor.getDocumentProvider().getDocument( + editor.getEditorInput()); + apply(marker, doc); + } + } + + /** + * Apply marker resolution for given marker in given open document. + * @param marker + * @param document + */ + public abstract void apply(IMarker marker, IDocument document); + + +} diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/checkers/ui/AbstractCodanCQuickFixProcessor.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/checkers/ui/AbstractCodanCQuickFixProcessor.java new file mode 100644 index 00000000000..1e8cc99febc --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/checkers/ui/AbstractCodanCQuickFixProcessor.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2009 Alena Laskavaia + * 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 + *******************************************************************************/ +package org.eclipse.cdt.codan.checkers.ui; + +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.core.resources.ResourceLookup; +import org.eclipse.cdt.ui.text.ICCompletionProposal; +import org.eclipse.cdt.ui.text.IInvocationContext; +import org.eclipse.cdt.ui.text.IProblemLocation; +import org.eclipse.cdt.ui.text.IQuickFixProcessor; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + +/** + * Abstract class IQuickFixProcessor - not used right now because it does not work + * properly for non hardcoded errors + *

+ * EXPERIMENTAL. This class or interface has been added as part + * of a work in progress. There is no guarantee that this API will work or that + * it will remain the same. + *

+ */ +public abstract class AbstractCodanCQuickFixProcessor implements IQuickFixProcessor { + /* + * (non-Javadoc) + * + * @see + * org.eclipse.cdt.ui.text.IQuickFixProcessor#hasCorrections(org.eclipse + * .cdt.ui.text.ITranslationUnit, int) + */ + public boolean hasCorrections(ITranslationUnit unit, int problemId) { + return problemId == 42; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.cdt.ui.text.IQuickFixProcessor#getCorrections(org.eclipse + * .cdt.ui.text.IInvocationContext, + * org.eclipse.cdt.ui.text.IProblemLocation[]) + */ + public ICCompletionProposal[] getCorrections(IInvocationContext context, + IProblemLocation[] locations) throws CoreException { + if (locations==null || locations.length==0) return null; + IProblemLocation loc = locations[0]; + IPath location= context.getTranslationUnit().getLocation(); + IFile astFile = ResourceLookup.selectFileForLocation(location, context.getTranslationUnit().getCProject().getProject()); + IMarker[] markers = astFile.findMarkers(loc.getMarkerType(), false, 1); + for (int i = 0; i < markers.length; i++) { + IMarker m = markers[i]; + int start = m.getAttribute(IMarker.CHAR_START, -1); + if (start==loc.getOffset()) { + String id = m.getAttribute(IMarker.PROBLEM,""); + return getCorrections(context, id, m); + } + } + + return null; + } + + public int getOffset(IMarker marker, IDocument doc) { + int charStart = marker.getAttribute(IMarker.CHAR_START, -1); + int position; + if (charStart > 0) { + position = charStart; + } else { + int line = marker.getAttribute(IMarker.LINE_NUMBER, -1) - 1; + try { + position = doc.getLineOffset(line); + } catch (BadLocationException e) { + return -1; + } + } + return position; + } + /** + * @param context + * @param loc + * @param marker + * @return + */ + public abstract ICCompletionProposal[] getCorrections(IInvocationContext context, + String problemId, IMarker marker); +} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CatchByReferenceQuickFix.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CatchByReferenceQuickFix.java new file mode 100644 index 00000000000..fa9f726ae00 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CatchByReferenceQuickFix.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2010 Alena Laskavaia + * 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 + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.checkers.ui.AbstarctCodanCMarkerResolution; +import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.FindReplaceDocumentAdapter; +import org.eclipse.jface.text.IDocument; + +public class CatchByReferenceQuickFix extends AbstarctCodanCMarkerResolution { + public String getLabel() { + return "Change to use reference"; + } + + public void apply(IMarker marker, IDocument document) { + FindReplaceDocumentAdapter dad = new FindReplaceDocumentAdapter( + document); + try { + int pos = getOffset(marker, document); + dad.find(pos, " ", /* forwardSearch *///$NON-NLS-1$ + true, /* caseSensitive */false, + /* wholeWord */false, /* regExSearch */false); + dad.replace(" & ", /* regExReplace */false); //$NON-NLS-1$ + } catch (BadLocationException e) { + CheckersUiActivator.log(e); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CodanProblemMarkerResolutionGenerator.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CodanProblemMarkerResolutionGenerator.java index 9c6870df365..90350190e04 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CodanProblemMarkerResolutionGenerator.java +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CodanProblemMarkerResolutionGenerator.java @@ -10,21 +10,133 @@ *******************************************************************************/ package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; -import java.util.regex.Matcher; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.regex.Pattern; +import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator; import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; import org.eclipse.ui.IMarkerResolution; import org.eclipse.ui.IMarkerResolutionGenerator; -public class CodanProblemMarkerResolutionGenerator implements IMarkerResolutionGenerator { +public class CodanProblemMarkerResolutionGenerator implements + IMarkerResolutionGenerator { + private static final String EXTENSION_POINT_NAME = "codanMarkerResolution"; //$NON-NLS-1$ + private static Map> resolutions = new HashMap>(); + private static boolean resolutionsLoaded = false; + + static class ConditionalResolution { + IMarkerResolution res; + String messagePattern; + + public ConditionalResolution(IMarkerResolution res2, + String messagePattern2) { + res = res2; + messagePattern = messagePattern2; + } + } + public IMarkerResolution[] getResolutions(IMarker marker) { - final Pattern patternBuildDependsAdd = Pattern.compile("Possible assignment in condition.*"); - String description = marker.getAttribute(IMarker.MESSAGE, "no message"); - Matcher matcherBuildDependsAdd = patternBuildDependsAdd.matcher(description); - if (matcherBuildDependsAdd.matches()) { - return new IMarkerResolution[] { new QuickFixAssignmentInCondition() }; + if (resolutionsLoaded == false) { + readExtensions(); + } + String id = marker.getAttribute(IMarker.PROBLEM, null); + if (id == null) + return new IMarkerResolution[0]; + String message = marker.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$ + Collection collection = resolutions.get(id); + if (collection != null) { + ArrayList list = new ArrayList(); + for (Iterator iterator = collection + .iterator(); iterator.hasNext();) { + ConditionalResolution res = iterator.next(); + if (res.messagePattern != null) { + if (message.matches(res.messagePattern)) + list.add(res.res); + } else { + list.add(res.res); + } + } + if (list.size() > 0) + return list.toArray(new IMarkerResolution[list.size()]); } return new IMarkerResolution[0]; } + + private static synchronized void readExtensions() { + IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint( + CheckersUiActivator.PLUGIN_ID, EXTENSION_POINT_NAME); + if (ep == null) + return; + try { + IConfigurationElement[] elements = ep.getConfigurationElements(); + // process categories + for (int i = 0; i < elements.length; i++) { + IConfigurationElement configurationElement = elements[i]; + processResolution(configurationElement); + } + } finally { + resolutionsLoaded = true; + } + } + + /** + * @param configurationElement + */ + private static void processResolution( + IConfigurationElement configurationElement) { + if (configurationElement.getName().equals("resolution")) { //$NON-NLS-1$ + String id = configurationElement.getAttribute("problemId"); //$NON-NLS-1$ + if (id == null) { + CheckersUiActivator.log("Extension for " + EXTENSION_POINT_NAME + + " problemId is not defined"); + return; + } + IMarkerResolution res; + try { + res = (IMarkerResolution) configurationElement + .createExecutableExtension("class");//$NON-NLS-1$ + } catch (CoreException e) { + CheckersUiActivator.log(e); + return; + } + String messagePattern = configurationElement + .getAttribute("messagePattern"); //$NON-NLS-1$ + if (messagePattern != null) { + try { + Pattern.compile(messagePattern); + } catch (Exception e) { + // bad pattern log and ignore + CheckersUiActivator.log("Extension for " + + EXTENSION_POINT_NAME + + " messagePattern is invalid: " + e.getMessage()); + return; + } + } + ConditionalResolution co = new ConditionalResolution(res, + messagePattern); + addResolution(id, co); + } + } + + public static void addResolution(String id, IMarkerResolution res, + String messagePattern) { + addResolution(id, new ConditionalResolution(res, messagePattern)); + } + + private static void addResolution(String id, ConditionalResolution res) { + Collection collection = resolutions.get(id); + if (collection == null) { + collection = new ArrayList(); + resolutions.put(id, collection); + } + collection.add(res); + } } \ No newline at end of file