diff options
author | Elliott Baron <ebaron@fedoraproject.org> | 2010-06-26 22:27:34 -0400 |
---|---|---|
committer | Elliott Baron <ebaron@fedoraproject.org> | 2010-06-26 22:27:34 -0400 |
commit | 4e112eca7750a4f530c986be55c178c43c16d3ea (patch) | |
tree | db140c4fe4db9945502398e4869707ca0346353e /org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param | |
parent | aa73b3f2503808e4b4029a73368a75b258d6f0dc (diff) | |
download | codan-master.tar.gz codan-master.tar.xz codan-master.zip |
* org.eclipse.cdt.codan.checkers.ui: Updated.
* org.eclipse.cdt.codan.checkers: Updated.
* org.eclipse.cdt.codan.core: Updated.
* org.eclipse.cdt.codan.ui: Updated.
* org.eclipse.cdt.codan.core.cxx: Added.
* org.eclipse.cdt.codan.extension/META-INF/MANIFEST.MF: Import org.eclipse.cdt.codan.core.cxx.model.
* org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/AbstractPropSimChecker.java: Superclass moved.
Diffstat (limited to 'org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param')
14 files changed, 1545 insertions, 0 deletions
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java new file mode 100644 index 0000000..91969fc --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/AbstractProblemPreference.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2009, 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.core.param; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StreamTokenizer; + +/** + * Default implementation of problem preference. It keeps preference metadata + * together with preference value. Some implementations may separate them. + * + */ +public abstract class AbstractProblemPreference implements IProblemPreference { + /** + * default key for a preference + */ + public static final String PARAM = "params"; //$NON-NLS-1$ + private String key = PARAM; + private String label = ""; //$NON-NLS-1$ + private String toolTip = null; + private String uiInfo; + private IProblemPreference parent; + + public String getLabel() { + return label; + } + + public String getToolTip() { + return toolTip; + } + + public String getKey() { + return key; + } + + public String getUiInfo() { + return uiInfo; + } + + /** + * Set preference key for itself + * + * @param key + */ + public void setKey(String key) { + if (key == null) + throw new NullPointerException("key"); //$NON-NLS-1$ + if (isValidIdentifier(key)) + this.key = key; + else + throw new IllegalArgumentException( + "Key must have java identifier syntax or number, i.e no dots and other funky stuff: " + key); //$NON-NLS-1$ + } + + protected boolean isValidIdentifier(String id) { + if (id == null) + return false; + int n = id.length(); + if (n == 0) + return false; + if (id.equals("#")) //$NON-NLS-1$ + return true; + for (int i = 0; i < n; i++) + if (!Character.isJavaIdentifierPart(id.charAt(i))) + return false; + return true; + } + + /** + * Sets a label for UI control + * + * @param label + */ + public void setLabel(String label) { + if (label == null) + throw new NullPointerException("Label cannot be null"); //$NON-NLS-1$ + this.label = label; + } + + /** + * Sets tooltip for ui control. Not supported now. + * + * @param tooltip + */ + public void setToolTip(String tooltip) { + this.toolTip = tooltip; + } + + /** + * Sets uiinfo for ui control. Not supported now. + * + * @param uiinfo + */ + public void setUiInfo(String uiinfo) { + this.uiInfo = uiinfo; + } + + public Object getValue() { + throw new UnsupportedOperationException(); + } + + public void setValue(Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + + /** + * @param str + * @return + */ + protected StreamTokenizer getImportTokenizer(String str) { + ByteArrayInputStream st = new ByteArrayInputStream(str.getBytes()); + StreamTokenizer tokenizer = new StreamTokenizer(new InputStreamReader( + st)); + tokenizer.resetSyntax(); + tokenizer.quoteChar('"'); + tokenizer.wordChars('_', '_'); + tokenizer.wordChars('-', '-'); + tokenizer.wordChars('.', '.'); + tokenizer.wordChars('0', '9'); + tokenizer.wordChars('a', 'z'); + tokenizer.wordChars('A', 'Z'); + tokenizer.wordChars(128 + 32, 255); + tokenizer.whitespaceChars(0, ' '); + tokenizer.commentChar('/'); + return tokenizer; + } + + public IProblemPreference getParent() { + return parent; + } + + /** + * @param parent + * the parent to set + */ + public void setParent(IProblemPreference parent) { + this.parent = parent; + } + + public String getQualifiedKey() { + if (parent == null) + return getKey(); + return parent.getQualifiedKey() + "." + getKey(); //$NON-NLS-1$ + } + + /** + * @param tokenizer + * @throws IOException + */ + public abstract void importValue(StreamTokenizer tokenizer) + throws IOException; + + public void importValue(String str) { + StreamTokenizer tokenizer = getImportTokenizer(str); + try { + importValue(tokenizer); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(str, e); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + protected String escape(String x) { + x = x.replaceAll("[\"\\\\]", "\\\\$0"); //$NON-NLS-1$//$NON-NLS-2$ + return "\"" + x + "\""; //$NON-NLS-1$//$NON-NLS-2$ + } + + /** + * @param str + * @return + */ + protected String unescape(String str) { + StreamTokenizer tokenizer = getImportTokenizer(str); + try { + tokenizer.nextToken(); + } catch (IOException e) { + return null; + } + String sval = tokenizer.sval; + return sval; + } +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java new file mode 100644 index 0000000..fd146b0 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/BasicProblemPreference.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2009, 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.core.param; + +import java.io.File; +import java.io.IOException; +import java.io.StreamTokenizer; +import java.util.regex.Pattern; + +/** + * Preference representing a problem preference of a basic type. + * + * @see IProblemPreferenceDescriptor.PreferenceType for types. + * + */ +public class BasicProblemPreference extends AbstractProblemPreference { + protected Object value; + private PreferenceType type = PreferenceType.TYPE_STRING; + + public PreferenceType getType() { + return type; + } + + /** + * Set preferene type + * + * @param type + */ + public void setType(PreferenceType type) { + if (type == null) + throw new NullPointerException("Type cannot be null"); //$NON-NLS-1$ + this.type = type; + } + + /** + * Generate an info with given key and label + * + * @param key + * - property id (use in actual property hash of a checker) + * @param label + * - label to be shown to user + * @param type + * - parameter type + */ + public BasicProblemPreference(String key, String label, PreferenceType type) { + this(key, label); + setType(type); + } + + /** + * Generate an info with given key and label + * + * @param key + * - property id (use in actual property hash of a checker) + * @param label + * - label to be shown to user + */ + public BasicProblemPreference(String key, String label) { + setKey(key); + setLabel(label); + } + + @Override + public void setValue(Object value) { + this.value = value; + } + + @Override + public Object getValue() { + return value; + } + + public String exportValue() { + Pattern pat = Pattern.compile("^[A-Za-z0-9._-]+$"); //$NON-NLS-1$ + String x = String.valueOf(getValue()); + if (pat.matcher(x).find() == false) + return escape(x); + return x; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.cdt.codan.core.param.IProblemPreferenceValue#importValue( + * java.lang.String) + */ + @Override + public void importValue(String str) { + if (str.startsWith("\"")) //$NON-NLS-1$ + str = unescape(str); + switch (getType()) { + case TYPE_STRING: + setValue(str); + break; + case TYPE_INTEGER: + setValue(Integer.parseInt(str)); + break; + case TYPE_BOOLEAN: + setValue(Boolean.valueOf(str)); + break; + case TYPE_FILE: + setValue(new File(str)); + break; + default: + throw new IllegalArgumentException(getType() + + " is not supported for basic type"); //$NON-NLS-1$ + } + } + + @Override + public String toString() { + return "(" + type + ")" + getKey() + ((value == null) ? "" : "=" + value); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$ + } + + @Override + public void importValue(StreamTokenizer tokenizer) { + try { + tokenizer.nextToken(); + String val = tokenizer.sval; + importValue(val); + } catch (IOException e) { + new IllegalArgumentException(e); + } + } +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries new file mode 100644 index 0000000..4f3cdf4 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Entries @@ -0,0 +1,10 @@ +/AbstractProblemPreference.java/1.8/Thu Jun 3 17:01:53 2010//TCDT_7_0_0 +/BasicProblemPreference.java/1.7/Thu Jun 3 17:01:53 2010//TCDT_7_0_0 +/FileScopeProblemPreference.java/1.4/Wed Jun 2 00:39:31 2010//TCDT_7_0_0 +/IProblemPreference.java/1.3/Tue May 25 01:33:22 2010//TCDT_7_0_0 +/IProblemPreferenceCompositeDescriptor.java/1.4/Mon May 31 02:53:25 2010//TCDT_7_0_0 +/IProblemPreferenceCompositeValue.java/1.4/Tue Jun 1 02:24:14 2010//TCDT_7_0_0 +/IProblemPreferenceDescriptor.java/1.6/Thu Jun 3 17:01:53 2010//TCDT_7_0_0 +/IProblemPreferenceValue.java/1.4/Tue Jun 1 02:24:14 2010//TCDT_7_0_0 +/ListProblemPreference.java/1.6/Tue Jun 1 02:24:14 2010//TCDT_7_0_0 +/MapProblemPreference.java/1.6/Tue Jun 1 02:24:14 2010//TCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository new file mode 100644 index 0000000..d959de5 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Repository @@ -0,0 +1 @@ +org.eclipse.cdt/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root new file mode 100644 index 0000000..04efa23 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@dev.eclipse.org:/cvsroot/tools diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag new file mode 100644 index 0000000..49a449a --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/CVS/Tag @@ -0,0 +1 @@ +NCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java new file mode 100644 index 0000000..bdb36f0 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/FileScopeProblemPreference.java @@ -0,0 +1,267 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +import java.io.IOException; +import java.io.StreamTokenizer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.cdt.codan.core.Messages; +import org.eclipse.cdt.codan.internal.core.CharOperation; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Custom preference for resource scope + * + * @noextend This class is not intended to be extended by clients. + * @since 1.0 + */ +public class FileScopeProblemPreference extends AbstractProblemPreference { + /** + * Key for the scope preference + */ + public static final String KEY = "fileScope"; //$NON-NLS-1$ + /** + * Exclusion attribute + */ + public static final String EXCLUSION = "exclusion"; //$NON-NLS-1$ + /** + * Inclusion attribute + */ + public static final String INCLUSION = "inclusion"; //$NON-NLS-1$ + private IResource resource; + private IPath[] inclusion = new IPath[0]; + private IPath[] exclusion = new IPath[0]; + + /** + * Default constructor + */ + public FileScopeProblemPreference() { + setKey(KEY); + setLabel(Messages.FileScopeProblemPreference_Label); + } + + public PreferenceType getType() { + return PreferenceType.TYPE_CUSTOM; + } + + /** + * Get attribute. Possible keys are EXCUSION and INCLUSION + * + * @param key + * @return class attribute for given key + */ + public IPath[] getAttribute(String key) { + if (key == EXCLUSION) + return exclusion; + if (key == INCLUSION) + return inclusion; + return null; + } + + /** + * Set attribute to a value. Possible keys are EXCUSION and INCLUSION + * + * @param key + * @param value + */ + public void setAttribute(String key, IPath[] value) { + if (key == EXCLUSION) + exclusion = value.clone(); + if (key == INCLUSION) + inclusion = value.clone(); + } + + /** + * @return null for workspace, or project of the resource it is applicable + * for + */ + public IProject getProject() { + if (resource != null) + return resource.getProject(); + return null; + } + + /** + * @return path of the resource it is applicable to + */ + public IPath getPath() { + if (resource != null) + return resource.getFullPath(); + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IWorkspaceRoot root = workspace.getRoot(); + return root.getFullPath(); + } + + /** + * @param resource + * the resource to set + */ + public void setResource(IResource resource) { + this.resource = resource; + } + + /** + * @return the resource for which scope is define. Null if workspace. + */ + public IResource getResource() { + return resource; + } + + public String exportValue() { + return exportPathList(INCLUSION, inclusion) + "," //$NON-NLS-1$ + + exportPathList(EXCLUSION, exclusion); + } + + protected String exportPathList(String key, IPath[] arr) { + String res = key + "=>("; //$NON-NLS-1$ + for (int i = 0; i < arr.length; i++) { + if (i != 0) + res += ","; //$NON-NLS-1$ + res += escape(arr[i].toPortableString()); + } + return res + ")"; //$NON-NLS-1$ + } + + @Override + public void importValue(StreamTokenizer tokenizer) throws IOException { + List<IPath> inc = importPathList(tokenizer, INCLUSION); + inclusion = inc.toArray(new IPath[inc.size()]); + checkChar(tokenizer, ','); + List<IPath> exc = importPathList(tokenizer, EXCLUSION); + exclusion = exc.toArray(new IPath[exc.size()]); + } + + private void checkChar(StreamTokenizer tokenizer, char c) + throws IOException { + tokenizer.nextToken(); + if (tokenizer.ttype != c) + throw new IllegalArgumentException("Expected " + c); //$NON-NLS-1$ + } + + private void checkKeyword(StreamTokenizer tokenizer, String keyword) + throws IOException { + tokenizer.nextToken(); + if (tokenizer.sval == null || !tokenizer.sval.equals(keyword)) + throw new IllegalArgumentException("Expected " + keyword); //$NON-NLS-1$ + } + + protected List<IPath> importPathList(StreamTokenizer tokenizer, + String keyword) throws IOException { + checkKeyword(tokenizer, keyword); + checkChar(tokenizer, '='); + checkChar(tokenizer, '>'); + ArrayList<IPath> list = new ArrayList<IPath>(); + int token; + int index = 0; + try { + checkChar(tokenizer, '('); + token = tokenizer.nextToken(); + if (token != ')') + tokenizer.pushBack(); + else + return Collections.emptyList(); + while (true) { + token = tokenizer.nextToken(); + if (tokenizer.sval == null) + throw new IllegalArgumentException(); + list.add(new Path(tokenizer.sval)); + token = tokenizer.nextToken(); + if (token == ')') + break; + tokenizer.pushBack(); + checkChar(tokenizer, ','); + index++; + } + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + return list; + } + + @Override + public Object getValue() { + return this; + } + + @Override + public void setValue(Object value) { + if (this == value) + return; + FileScopeProblemPreference scope = (FileScopeProblemPreference) value; + setAttribute(INCLUSION, scope.getAttribute(INCLUSION)); + setAttribute(EXCLUSION, scope.getAttribute(EXCLUSION)); + this.resource = scope.getResource(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.param.AbstractProblemPreference#clone() + */ + @Override + public Object clone() { + FileScopeProblemPreference scope = (FileScopeProblemPreference) super + .clone(); + scope.setValue(this); + return scope; + } + + /** + * Checks that resource denotated by the given path is in scope (defined by + * exclusion/inclusion settings of this class). In inclusion list is defined + * check first if it belongs to it, returns false if not. + * Then checks if it belongs to exclusion list and return false if it is. + * + * @param path + * - resource path + * @return true is given path is in scope + */ + public boolean isInScope(IPath path) { + //System.err.println("test " + file + " " + exportValue()); + if (inclusion.length > 0) { + if (!matchesFilter(path, inclusion)) + return false; + } + if (exclusion.length > 0) { + if (matchesFilter(path, exclusion)) + return false; + } + return true; + } + + /** + * Checks that given path matches on the paths provided as second argument + * + * @param resourcePath - resource path + * @param paths - array of path patterns, for pattern see + * {@link CharOperation#pathMatch} + * @return true if matches with at least one pattern in the array + */ + public boolean matchesFilter(IPath resourcePath, IPath[] paths) { + char[] path = resourcePath.toString().toCharArray(); + for (int i = 0, length = paths.length; i < length; i++) { + char[] pattern = paths[i].toString().toCharArray(); + if (CharOperation.pathMatch(pattern, path, true, '/')) { + return true; + } + } + return false; + } +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java new file mode 100644 index 0000000..6b0c316 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +/** + * Problem preference. If problem has more than one it can be composite, i.e. + * map. Instead of implementing this interface clients must extend + * {@link AbstractProblemPreference} class. + * + * Problem Preference constist of preference metadata + * (IProblemPreferenceDescriptor) + * and value of preference (IProblemPreferenceValue). + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IProblemPreference extends Cloneable, IProblemPreferenceValue, + IProblemPreferenceDescriptor { +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java new file mode 100644 index 0000000..392e0a2 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeDescriptor.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +/** + * Composite descriptor. For descriptors like map and list. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IProblemPreferenceCompositeDescriptor { + /** + * Available if type is composite. Returns value of subdescriptor with the + * name of key. For the "list" type key is the number (index). + * + * @param key + * - name of the subdescriptor. + * @return child preference of the given key + */ + IProblemPreference getChildDescriptor(String key); + + /** + * Available for composite types. Returns array of children. + * + * @return array of children. 0 size of none. + */ + IProblemPreference[] getChildDescriptors(); + + /** + * Add preference + * + * @param preference + * @return added preference + */ + IProblemPreference addChildDescriptor(IProblemPreference preference); + + /** + * Remove preference + * + * @param preference + */ + void removeChildDescriptor(IProblemPreference preference); +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java new file mode 100644 index 0000000..f44a659 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceCompositeValue.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2009,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.core.param; + +/** + * Interface for container type preferences, such as map or list + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IProblemPreferenceCompositeValue { + /** + * Returns value of the child element of a given key + * + * @param key + * @return value of the child preference + */ + Object getChildValue(String key); + + /** + * Sets the value of the child element of a given key + * + * @param key + * @param value + */ + void setChildValue(String key, Object value); + + /** + * Removes child element matching the given key + * + * @param key + */ + void removeChildValue(String key); +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java new file mode 100644 index 0000000..f6f97e0 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceDescriptor.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2009, 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.core.param; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * Problem parameter usually key=value settings that allows to alter checker + * behaviour for given problem. For example if checker finds violation of naming + * conventions for function, parameter would be the pattern of allowed names. + * + * IProblemPreferenceDescriptor represent preference's meta-info for the ui. If + * more than one parameter is required it can be map or list of sub-preferences. + * This is only needed for auto-generated ui for parameter + * editing. For more complex cases custom ui control should be used. Extend + * {@link AbstractProblemPreference} class + * to implement this interface. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IProblemPreferenceDescriptor extends Cloneable { + /** + * Type of the user preference + */ + public enum PreferenceType { + /** + * String type, represented by string input field by default + */ + TYPE_STRING("string"), //$NON-NLS-1$ + /** + * Integer type, represented by integer input field by default + */ + TYPE_INTEGER("integer"), //$NON-NLS-1$ + /** + * Boolean type, represented by checkbox (boolean input field) + */ + TYPE_BOOLEAN("boolean"), //$NON-NLS-1$ + /** + * File type, represented by file picker input field + */ + TYPE_FILE("file"), //$NON-NLS-1$ + /** + * List type, represented by list (table) control + */ + TYPE_LIST("list"), //$NON-NLS-1$ + /** + * Map type, represented by composite of children fields + */ + TYPE_MAP("map"), //$NON-NLS-1$ + /** + * Custom type, represented by string input field by default + */ + TYPE_CUSTOM("custom"); //$NON-NLS-1$ + private String literal; + + private PreferenceType(String literal) { + this.literal = literal; + } + + /** + * @param name - name of the type literal (i.e. comes from name() or + * toString()) + * @return type represented by this name + */ + public static PreferenceType valueOfLiteral(String name) { + PreferenceType[] values = values(); + for (int i = 0; i < values.length; i++) { + PreferenceType e = values[i]; + if (e.literal.equals(name)) + return e; + } + return null; + } + + @Override + public String toString() { + return literal; + } + + /** + * @param value + * @return parameter type corresponding to the value java type + */ + public static PreferenceType typeOf(Object value) { + if (value instanceof Boolean) + return TYPE_BOOLEAN; + if (value instanceof String) + return TYPE_STRING; + if (value instanceof Integer) + return TYPE_INTEGER; + if (value instanceof File) + return TYPE_FILE; + if (value instanceof List) + return TYPE_LIST; + if (value instanceof Map) + return TYPE_MAP; + return TYPE_CUSTOM; + } + } + + /** + * Key of the preference. Key must be java-like identified or number. Cannot + * contain dots. Cannot be null. + * + * @return key + */ + String getKey(); + + /** + * type of the parameter, supports boolean, integer, string, file, list and + * map. For list type child preference can be + * accessed by number (index), if map is the type child preference can be + * accessed by a key (string) + * + * @return type of the preference + */ + PreferenceType getType(); + + /** + * Additional info on how it is represented in the ui, for example boolean + * can be represented as checkbox, drop-down and so on, Values TBD. + * Not supported at the moment. + * + * @return ui info or null if not set + */ + String getUiInfo(); + + /** + * User visible label for the parameter control in UI + * + * @return the label + */ + String getLabel(); + + /** + * Detailed explanation of parameter. Not supported at the moment. + * + * @return the toolTip text + */ + String getToolTip(); + + /** + * default clone implementation + * + * @return clone of the object + */ + Object clone(); + + /** + * @return parent preference + */ + IProblemPreference getParent(); + + /** + * Combined key of values from parents plus itself separated by dot + * + * @return qualified key + */ + String getQualifiedKey(); +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java new file mode 100644 index 0000000..cbe9f4f --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/IProblemPreferenceValue.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +/** + * Value of the problem preference. If more than one it can be composite, i.e. + * map.Extend {@link AbstractProblemPreference} class + * to implement this interface. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IProblemPreferenceValue extends Cloneable { + /** + * Get value of preference. + * + * @return object that represents the value. Limited number of object types + * are allowed. + * @see IProblemPreferenceDescriptor.PreferenceType + */ + Object getValue(); + + /** + * Set value of preference represented by this object. + * + * @param value + */ + void setValue(Object value); + + /** + * Export value in string representation required for storing in eclipse + * preferences. + * + * @return string representation of the value + */ + String exportValue(); + + /** + * Import value from string into internal object state. + * + * @param str + * - string from preferences, previously exported by exportValue + * method. + */ + void importValue(String str); +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java new file mode 100644 index 0000000..333cb31 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/ListProblemPreference.java @@ -0,0 +1,323 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +import java.io.IOException; +import java.io.StreamTokenizer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; + +/** + * List implementation of IProblemPreference. + * + * @noextend This class is not intended to be extended by clients. + */ +public class ListProblemPreference extends AbstractProblemPreference implements + IProblemPreferenceCompositeValue, IProblemPreferenceCompositeDescriptor { + /** + * Constant that represent a key for "shared" child preference (descriptor) + * of all elements + */ + public static final String COMMON_DESCRIPTOR_KEY = "#"; //$NON-NLS-1$ + protected ArrayList<Object> list = new ArrayList<Object>(); + protected IProblemPreference childDescriptor; + + /** + * @param key + * - key to access this preference + * @param label + * - label to be shown in UI + */ + public ListProblemPreference(String key, String label) { + setKey(key); + setLabel(label); + } + + public PreferenceType getType() { + return PreferenceType.TYPE_LIST; + } + + /** + * Set child descriptor (all elements have the same). Value and key + * of it would be ignored and reset. + * + * @param desc + * @return set child descriptor + */ + public IProblemPreference setChildDescriptor(IProblemPreference desc) { + childDescriptor = desc; + if (desc != null) { + childDescriptor.setValue(null); + ((AbstractProblemPreference) childDescriptor) + .setKey(COMMON_DESCRIPTOR_KEY); + } + return desc; + } + + /** + * Sets common descriptor for all elements, if value if not null sets the + * value for its key also. Do not make assumptions of values of desc after + * you pass it to this function. + * + * @return read only preference matching the key + */ + public IProblemPreference addChildDescriptor(IProblemPreference desc) { + Object value = desc.getValue(); + String key = desc.getKey(); + setChildDescriptor(desc); + setChildValue(key, value); + return getChildDescriptor(key); + } + + /** + * + * @return descriptor of the child elements + */ + public IProblemPreference getChildDescriptor() { + return childDescriptor; + } + + /** + * Returns cloned descriptor of the i'th child. Modifying return value would + * not affect internal state of the list element. + * + * @param i - index of the element + * @return child preference + */ + public IProblemPreference getChildDescriptor(int i) { + Object value = list.get(i); + AbstractProblemPreference desc = (AbstractProblemPreference) childDescriptor + .clone(); + desc.setKey(String.valueOf(i)); + desc.setValue(value); + return desc; + } + + /** + * Get read only problem preference for element equal to key's int value. + * If key is null or # return generic descriptor with null value. + * + * @throws NumberFormatException + * if key is not number + */ + public IProblemPreference getChildDescriptor(String key) + throws NumberFormatException { + if (key == null || key.equals(COMMON_DESCRIPTOR_KEY)) { + // return common descriptor + return getChildDescriptor(); + } + Integer iv = Integer.valueOf(key); + if (iv.intValue() >= list.size()) { + // create one + AbstractProblemPreference clone = (AbstractProblemPreference) childDescriptor + .clone(); + clone.setKey(key); + return clone; + } + return getChildDescriptor(iv.intValue()); + } + + /** + * Return array of clones values of child preferences. + */ + public IProblemPreference[] getChildDescriptors() { + IProblemPreference[] res = new IProblemPreference[list.size()]; + for (int i = 0; i < res.length; i++) { + res[i] = getChildDescriptor(i); + } + return res; + } + + public Object getChildValue(String key) { + int index = Integer.parseInt(key); + return getChildValue(index); + } + + /** + * @param index - index of the element + * @return child value by index + */ + public Object getChildValue(int index) { + return list.get(index); + } + + public void setChildValue(String key, Object value) { + int i = Integer.valueOf(key).intValue(); + setChildValue(i, value); + } + + /** + * @param i - index of the element + * @param value - value of the child element + */ + public void setChildValue(int i, Object value) { + if (value != null) { + while (i >= list.size()) { + list.add(null); + } + list.set(i, value); + } else { + while (i == list.size() - 1) { + list.remove(i); + } + } + } + + /** + * Adds value to the list + * + * @param value + */ + public void addChildValue(Object value) { + list.add(value); + } + + /** + * Removes child value by key + */ + public void removeChildValue(String key) { + int index = Integer.parseInt(key); + list.remove(index); + } + + @Override + public Object clone() { + ListProblemPreference list1 = (ListProblemPreference) super.clone(); + list1.list = new ArrayList<Object>(); + list1.setChildDescriptor((IProblemPreference) getChildDescriptor() + .clone()); + for (Iterator<Object> iterator = list.iterator(); iterator.hasNext();) { + Object value = iterator.next(); + list1.addChildValue(value); + } + return list1; + } + + public String exportValue() { + StringBuffer buf = new StringBuffer("("); //$NON-NLS-1$ + for (Iterator<Object> iterator = list.iterator(); iterator.hasNext();) { + IProblemPreference d = (IProblemPreference) childDescriptor.clone(); + d.setValue(iterator.next()); + buf.append(d.exportValue()); + if (iterator.hasNext()) + buf.append(","); //$NON-NLS-1$ + } + return buf.toString() + ")"; //$NON-NLS-1$ + } + + @Override + public void importValue(String str) { + StreamTokenizer tokenizer = getImportTokenizer(str); + try { + importValue(tokenizer); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(str, e); + } + } + + @Override + public void importValue(StreamTokenizer tokenizer) { + clear(); + int token; + int index = 0; + try { + token = tokenizer.nextToken(); + String chara = String.valueOf((char) token); + if (token != '(') + throw new IllegalArgumentException(chara); + token = tokenizer.nextToken(); + if (token != ')') + tokenizer.pushBack(); + else + return; + while (true) { + String ik = String.valueOf(index); + IProblemPreference desc = getChildDescriptor(ik); + if (desc != null && desc instanceof AbstractProblemPreference) { + ((AbstractProblemPreference) desc).importValue(tokenizer); + setChildValue(ik, desc.getValue()); + } + token = tokenizer.nextToken(); + if (token == ')') + break; + if (token != ',') + throw new IllegalArgumentException(chara); + index++; + } + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * If info key is '#' resets common descriptor to null, otherwise removes + * value + */ + public void removeChildDescriptor(IProblemPreference info) { + if (info.getKey().equals(COMMON_DESCRIPTOR_KEY)) + setChildDescriptor(null); + else + removeChildValue(info.getKey()); + } + + /** + * @return children size + */ + public int size() { + return list.size(); + } + + /** + * Removes all values from the list + */ + public void clear() { + list.clear(); + } + + /** + * @return array of values of children elements. + */ + @Override + public Object getValue() { + return getValues(); + } + + /** + * Sets list value to values of array given as argument. + * + * @param value - must be Object[] + */ + @Override + public void setValue(Object value) { + Object[] values = (Object[]) value; + if (Arrays.deepEquals(getValues(), values)) { + return; + } + list.clear(); + for (int i = 0; i < values.length; i++) { + Object object = values[i]; + list.add(object); + } + } + + @Override + public String toString() { + return childDescriptor + ":" + list.toString(); //$NON-NLS-1$ + } + + /** + * @return array of values of children elements. + */ + public Object[] getValues() { + return list.toArray(new Object[list.size()]); + } +} diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java new file mode 100644 index 0000000..6e865f0 --- /dev/null +++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +import java.io.IOException; +import java.io.StreamTokenizer; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences; + +/** + * MapProblemPreference - for checker that needs more than one preferences and + * they all differently "named". + * For example checker for parameter names shadowing would have two boolean + * options: + * "check contructors" and + * "check setters". In this case you use this type. + * {@link AbstractCheckerWithProblemPreferences} class has map as default top + * level parameter preference. + * + * @noextend This class is not intended to be extended by clients. + */ +public class MapProblemPreference extends AbstractProblemPreference implements + IProblemPreferenceCompositeValue, IProblemPreferenceCompositeDescriptor { + protected LinkedHashMap<String, IProblemPreference> hash = new LinkedHashMap<String, IProblemPreference>(); + + /** + * Default constuctor + */ + public MapProblemPreference() { + super(); + } + + /** + * @param key + * - key for itself + * @param label + * - label for this group of parameters + */ + public MapProblemPreference(String key, String label) { + setKey(key); + setLabel(label); + } + + public PreferenceType getType() { + return PreferenceType.TYPE_MAP; + } + + /** + * Get parameter preference for element by key + * + */ + public IProblemPreference getChildDescriptor(String key) { + return hash.get(key); + } + + /** + * Adds or replaces child descriptor and value for the element with the key + * equals to desc.getKey(). The desc object would be put in the map, some of + * its field may be modified. + * + * @param desc + */ + public IProblemPreference addChildDescriptor(IProblemPreference desc) { + ((AbstractProblemPreference) desc).setParent(this); + hash.put(desc.getKey(), desc); + return desc; + } + + /** + * Return list of child descriptors. Client should threat returned value as + * read only, + * and not assume that modifying its elements would modify actual child + * values. + */ + public IProblemPreference[] getChildDescriptors() { + return hash.values().toArray( + new IProblemPreference[hash.values().size()]); + } + + /** + * Returns value of the child element by its key + */ + public Object getChildValue(String key) { + IProblemPreference childInfo = getChildDescriptor(key); + return childInfo.getValue(); + } + + /** + * Set child value by its key + */ + public void setChildValue(String key, Object value) { + IProblemPreference pref = getChildDescriptor(key); + if (pref == null) + throw new IllegalArgumentException("Preference for " + key //$NON-NLS-1$ + + " must exists before setting its value"); //$NON-NLS-1$ + pref.setValue(value); + hash.put(key, pref); // cannot assume getChildDescriptor returns shared value + } + + /** + * Removes child value and descriptor by key + */ + public void removeChildValue(String key) { + hash.remove(key); + } + + @Override + public Object clone() { + MapProblemPreference map = (MapProblemPreference) super.clone(); + map.hash = new LinkedHashMap<String, IProblemPreference>(); + for (Iterator<String> iterator = hash.keySet().iterator(); iterator + .hasNext();) { + String key = iterator.next(); + map.hash.put(key, (IProblemPreference) hash.get(key).clone()); + } + return map; + } + + public String exportValue() { + StringBuffer buf = new StringBuffer("{"); //$NON-NLS-1$ + for (Iterator<String> iterator = hash.keySet().iterator(); iterator + .hasNext();) { + String key = iterator.next(); + IProblemPreference d = hash.get(key); + buf.append(key + "=>" + d.exportValue()); //$NON-NLS-1$ + if (iterator.hasNext()) + buf.append(","); //$NON-NLS-1$ + } + return buf.toString() + "}"; //$NON-NLS-1$ + } + + @Override + public void importValue(String str) { + StreamTokenizer tokenizer = getImportTokenizer(str); + try { + importValue(tokenizer); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(str + ":" + e.toString(), e); //$NON-NLS-1$ + } + } + + /** + * @param tokenizer + */ + @Override + public void importValue(StreamTokenizer tokenizer) { + int token; + try { + token = tokenizer.nextToken(); + String chara = String.valueOf((char) token); + if (token != '{') { + throw new IllegalArgumentException(chara); + } + while (true) { + token = tokenizer.nextToken(); + String key = tokenizer.sval; + token = tokenizer.nextToken(); + if (token != '=') + throw new IllegalArgumentException(chara); + token = tokenizer.nextToken(); + if (token != '>') + throw new IllegalArgumentException(chara); + IProblemPreference desc = getChildDescriptor(key); + if (desc != null && desc instanceof AbstractProblemPreference) { + ((AbstractProblemPreference) desc).importValue(tokenizer); + setChildValue(key, desc.getValue()); + } + token = tokenizer.nextToken(); + if (token == '}') + break; + if (token != ',') + throw new IllegalArgumentException(chara); + } + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Removes child descriptor by its key + */ + public void removeChildDescriptor(IProblemPreference info) { + hash.remove(info.getKey()); + } + + /** + * @return size of the map + */ + public int size() { + return hash.size(); + } + + /** + * Clears the map + */ + public void clear() { + hash.clear(); + } + + @Override + public String toString() { + return hash.values().toString(); + } + + /** + * Value of this preference is a map key=>value of child preferences. + * Modifying this returned map would not change internal state of this + * object. + */ + @Override + public Object getValue() { + LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(); + for (Iterator<IProblemPreference> iterator = hash.values().iterator(); iterator + .hasNext();) { + IProblemPreference pref = iterator.next(); + map.put(pref.getKey(), pref.getValue()); + } + return map; + } + + /** + * Set values for this object child elements. Elements are not present in + * this map would be removed. + * Preference descriptors for the keys must be set before calling this + * method, unless value if instanceof {@link IProblemPreference}. + * + * @param value - must be Map<String,Object> + */ + @SuppressWarnings("unchecked") + @Override + public void setValue(Object value) { + Map<String, Object> map = (Map<String, Object>) value; + LinkedHashMap<String, IProblemPreference> hash2 = (LinkedHashMap<String, IProblemPreference>) hash + .clone(); + hash.clear(); + for (Iterator<String> iterator = map.keySet().iterator(); iterator + .hasNext();) { + String key = iterator.next(); + Object value2 = map.get(key); + if (value2 instanceof IProblemPreference) { + hash.put(key, (IProblemPreference) value2); + } else { + setChildValue(key, value2); + IProblemPreference pref = hash2.get(key); + pref.setValue(value2); + hash.put(key, pref); + } + } + } +} |