diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java index 7f284744356..11d8fe88c22 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java @@ -20,7 +20,7 @@ public interface ICModelMarker { /** * C model problem marker type (value "org.eclipse.cdt.core.problem"). * This can be used to recognize those markers in the workspace that flag problems - * detected by the C ompilers. + * detected by the C compilers. */ public static final String C_MODEL_PROBLEM_MARKER = CCorePlugin.PLUGIN_ID + ".problem"; //$NON-NLS-1$ @@ -30,6 +30,15 @@ public interface ICModelMarker { * itself if it can be found. */ public static final String C_MODEL_MARKER_VARIABLE = "problem.variable"; //$NON-NLS-1$ + + /** + * C model task marker type (value "org.eclipse.cdt.core.task"). + * This can be used to recognize task markers in the workspace that correspond to tasks + * specified in C/C++ source comments and detected during translation (for example, 'TO-DO: ...'). + * Tasks are identified by a task tag, which can be customized through CCorePlugin + * option "org.eclipse.cdt.core.translation.taskTag". + */ + public static final String TASK_MARKER = CCorePlugin.PLUGIN_ID + ".task"; //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java index 0a830ea9f47..93d9ce181de 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java @@ -8,6 +8,8 @@ package org.eclipse.cdt.core.model; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; +import java.util.Map; + /** * A C project represents a view of a project resource in terms of C * elements such as , ICContainer, ITranslationUnit .... @@ -51,4 +53,59 @@ public interface ICProject extends ICContainer { * @return IProject */ IProject getProject(); + + /** + * Helper method for returning one option value only. Equivalent to (String)this.getOptions(inheritCCoreOptions).get(optionName) + * Note that it may answer null if this option does not exist, or if there is no custom value for it. + *

+ * For a complete description of the configurable options, see CCorePlugin#getDefaultOptions. + *

+ * + * @param optionName the name of an option + * @param inheritCCoreOptions - boolean indicating whether CCorePlugin options should be inherited as well + * @return the String value of a given option + * @see CCorePlugin#getDefaultOptions + */ + String getOption(String optionName, boolean inheritCCoreOptions); + + /** + * Returns the table of the current custom options for this project. Projects remember their custom options, + * in other words, only the options different from the the CCorePlugin global options for the workspace. + * A boolean argument allows to directly merge the project options with global ones from CCorePlugin. + *

+ * For a complete description of the configurable options, see CCorePlugin#getDefaultOptions. + *

+ * + * @param inheritCCoreOptions - boolean indicating whether CCorePlugin options should be inherited as well + * @return table of current settings of all options + * (key type: String; value type: String) + * @see CCorePlugin#getDefaultOptions + */ + Map getOptions(boolean inheritCCoreOptions); + + /** + * Helper method for setting one option value only. Equivalent to Map options = this.getOptions(false); map.put(optionName, optionValue); this.setOptions(map) + *

+ * For a complete description of the configurable options, see CCorePlugin#getDefaultOptions. + *

+ * + * @param optionName the name of an option + * @param optionValue the value of the option to set + * @see CCorePlugin#getDefaultOptions + */ + void setOption(String optionName, String optionValue); + + /** + * Sets the project custom options. All and only the options explicitly included in the given table + * are remembered; all previous option settings are forgotten, including ones not explicitly + * mentioned. + *

+ * For a complete description of the configurable options, see CCorePlugin#getDefaultOptions. + *

+ * + * @param newOptions the new options (key type: String; value type: String), + * or null to flush all custom options (clients will automatically get the global CCorePlugin options). + * @see CCorePlugin#getDefaultOptions + */ + void setOptions(Map newOptions); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder.java index d07551fed27..56ddb04463f 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder.java @@ -17,15 +17,20 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.HashSet; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.model.INamespace; import org.eclipse.cdt.core.model.IParent; import org.eclipse.cdt.core.model.IStructure; import org.eclipse.cdt.core.model.ITemplate; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.parser.ITranslationResult; import org.eclipse.cdt.core.parser.IParser; +import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.ParserFactory; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.internal.core.dom.ArrayQualifier; @@ -52,11 +57,20 @@ import org.eclipse.cdt.internal.core.dom.TemplateDeclaration; import org.eclipse.cdt.internal.core.dom.TemplateParameter; import org.eclipse.cdt.internal.core.dom.TranslationUnit; import org.eclipse.cdt.internal.core.dom.TypeSpecifier; +import org.eclipse.cdt.internal.core.parser.DefaultErrorHandlingPolicies; +import org.eclipse.cdt.internal.core.parser.TranslationResult; +import org.eclipse.cdt.internal.core.parser.TranslationOptions; +import org.eclipse.cdt.internal.core.parser.ITranslationResultRequestor; import org.eclipse.cdt.internal.core.parser.Name; +import org.eclipse.cdt.internal.core.parser.problem.DefaultProblemFactory; +import org.eclipse.cdt.internal.core.parser.problem.ProblemReporter; +import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; -public class CModelBuilder { +public class CModelBuilder implements ITranslationResultRequestor { protected org.eclipse.cdt.internal.core.model.TranslationUnit translationUnit; protected Map newElements; @@ -67,9 +81,38 @@ public class CModelBuilder { } public Map parse() throws Exception { - DOMBuilder domBuilder = new DOMBuilder(); - IParser parser = ParserFactory.createParser(ParserFactory.createScanner( new StringReader( translationUnit.getBuffer().getContents() ), null, null, null, ParserMode.QUICK_PARSE ), domBuilder, ParserMode.QUICK_PARSE); - + + DOMBuilder domBuilder = new DOMBuilder(); + + // create a problem reporter + Map options = null; + if (translationUnit != null && translationUnit.getCProject() != null) { + options = translationUnit.getCProject().getOptions(true); + } + TranslationOptions cOptions = new TranslationOptions(options); + ProblemReporter problemReporter = new ProblemReporter( + DefaultErrorHandlingPolicies.proceedWithAllProblems(), + cOptions, + new DefaultProblemFactory() + ); + + // create translation result + TranslationResult unitResult = new TranslationResult(translationUnit); + + IParser parser = ParserFactory.createParser( + ParserFactory.createScanner( + new StringReader( + translationUnit.getBuffer().getContents() + ), + null, null, null, + ParserMode.QUICK_PARSE, + problemReporter, unitResult + ), + domBuilder, + ParserMode.QUICK_PARSE, + problemReporter, unitResult + ); + if( translationUnit.getCProject() != null ) { IProject currentProject = translationUnit.getCProject().getProject(); @@ -95,6 +138,9 @@ public class CModelBuilder { System.out.println( "NullPointer exception generating CModel"); npe.printStackTrace(); } + + // process translation results + acceptResult(unitResult); // For the debuglog to take place, you have to call // Util.setDebugging(true); @@ -1009,4 +1055,100 @@ public class CModelBuilder { return name; } + + + /** + * @see ITranslatorRequestor#acceptResult(ITranslationResult) + */ + public void acceptResult(ITranslationResult result) { + ITranslationUnit translationUnit = result.getTranslationUnit(); + + try { + updateTasksFor(translationUnit, result); // record tasks + } catch (CoreException e) { + System.out.println("Exception while accepting parse results"); + e.printStackTrace(); + } + } + + protected void updateTasksFor(ITranslationUnit sourceFile, ITranslationResult result) throws CoreException { + IProblem[] tasks = result.getTasks(); + + storeTasksFor(sourceFile, tasks); + } + + protected void storeTasksFor(ITranslationUnit sourceFile, IProblem[] tasks) throws CoreException { + if (sourceFile == null) return; + + if (tasks == null) tasks = new IProblem[0]; + + IResource resource = sourceFile.getResource(); + IMarker[] existingTaskMarkers = resource.findMarkers(ICModelMarker.TASK_MARKER, false, IResource.DEPTH_ONE); + HashSet taskSet = new HashSet(); + + if (existingTaskMarkers != null) + for (int i=0; i 0)) { + for (int j = 0; j < existingTaskMarkers.length; j++) { + if ( + (((Integer) existingTaskMarkers[j].getAttribute(IMarker.LINE_NUMBER)).intValue() == task.getSourceLineNumber()) + && (((Integer) existingTaskMarkers[j].getAttribute(IMarker.PRIORITY)).intValue() == priority) + && (((Integer) existingTaskMarkers[j].getAttribute(IMarker.CHAR_START)).intValue() == task.getSourceStart()) + && (((Integer) existingTaskMarkers[j].getAttribute(IMarker.CHAR_END)).intValue() == task.getSourceEnd()+1) + && (((String) existingTaskMarkers[j].getAttribute(IMarker.MESSAGE)).equals(task.getMessage())) + ) { + taskSet.remove(existingTaskMarkers[j]); + continue taskLoop; + } + } + } + + IMarker marker = resource.createMarker(ICModelMarker.TASK_MARKER); + + marker.setAttributes( + new String[] { + IMarker.MESSAGE, + IMarker.PRIORITY, + IMarker.DONE, + IMarker.CHAR_START, + IMarker.CHAR_END, + IMarker.LINE_NUMBER, + IMarker.USER_EDITABLE, + }, + new Object[] { + task.getMessage(), + new Integer(priority), + new Boolean(false), + new Integer(task.getSourceStart()), + new Integer(task.getSourceEnd() + 1), + new Integer(task.getSourceLineNumber()), + new Boolean(false), + }); + } + } + + // Remove all obsolete markers + Iterator setI = taskSet.iterator(); + while (setI.hasNext()) { + IMarker marker = (IMarker)setI.next(); + marker.delete(); + } + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index e5287a378a7..5238ab37126 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -8,6 +8,7 @@ package org.eclipse.cdt.internal.core.model; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -45,10 +46,12 @@ import org.eclipse.cdt.internal.core.search.indexing.IndexManager; public class CModelManager implements IResourceChangeListener { - /** - * Unique handle onto the CModel - */ - final CModel cModel = new CModel(); + /** + * Unique handle onto the CModel + */ + final CModel cModel = new CModel(); + + public static HashSet OptionNames = new HashSet(20); /** * Used to convert IResourceDeltas into ICElementDeltas. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java index f96d6e787d5..776cf0d3a65 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java @@ -6,6 +6,10 @@ package org.eclipse.cdt.internal.core.model; */ import java.util.ArrayList; +import java.util.Iterator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CProjectNature; @@ -21,6 +25,8 @@ import org.eclipse.cdt.core.model.ILibraryReference; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Preferences; +import org.eclipse.core.runtime.QualifiedName; public class CProject extends CContainer implements ICProject { @@ -39,6 +45,8 @@ public class CProject extends CContainer implements ICProject { public IProject getProject() { return getUnderlyingResource().getProject(); } + + private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$ public ICElement findElement(IPath path) throws CModelException { ICElement celem = null; @@ -92,4 +100,149 @@ public class CProject extends CContainer implements ICProject { } return (ILibraryReference[])list.toArray(new ILibraryReference[0]); } + + /** + * @see org.eclipse.cdt.core.model.ICProject#getOption(String, boolean) + */ + public String getOption(String optionName, boolean inheritCCoreOptions) { + + if (CModelManager.OptionNames.contains(optionName)) { + Preferences preferences = getPreferences(); + + if (preferences == null || preferences.isDefault(optionName)) { + return inheritCCoreOptions ? CCorePlugin.getOption(optionName) : null; + } + + return preferences.getString(optionName).trim(); + } + + return null; + } + + /** + * @see org.eclipse.cdt.core.model.ICProject#getOptions(boolean) + */ + public Map getOptions(boolean inheritCCoreOptions) { + // initialize to the defaults from CCorePlugin options pool + Map options = inheritCCoreOptions ? CCorePlugin.getOptions() : new HashMap(5); + + Preferences preferences = getPreferences(); + if (preferences == null) return options; + HashSet optionNames = CModelManager.OptionNames; + + // get preferences set to their default + if (inheritCCoreOptions){ + String[] defaultPropertyNames = preferences.defaultPropertyNames(); + for (int i = 0; i < defaultPropertyNames.length; i++){ + String propertyName = defaultPropertyNames[i]; + if (optionNames.contains(propertyName)){ + options.put(propertyName, preferences.getDefaultString(propertyName).trim()); + } + } + } + // get custom preferences not set to their default + String[] propertyNames = preferences.propertyNames(); + for (int i = 0; i < propertyNames.length; i++){ + String propertyName = propertyNames[i]; + if (optionNames.contains(propertyName)){ + options.put(propertyName, preferences.getString(propertyName).trim()); + } + } + return options; + } + + /** + * @see org.eclipse.cdt.core.model.ICProject#setOption(java.lang.String, java.lang.String) + */ + public void setOption(String optionName, String optionValue) { + if (!CModelManager.OptionNames.contains(optionName)) return; // unrecognized option + + Preferences preferences = getPreferences(); + preferences.setDefault(optionName, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251) + preferences.setValue(optionName, optionValue); + + savePreferences(preferences); + } + + /** + * @see org.eclipse.cdt.core.model.ICProject#setOptions(Map) + */ + public void setOptions(Map newOptions) + { + Preferences preferences = new Preferences(); + setPreferences(preferences); // always reset (26255) + + if (newOptions != null){ + Iterator keys = newOptions.keySet().iterator(); + + while (keys.hasNext()){ + String key = (String)keys.next(); + if (!CModelManager.OptionNames.contains(key)) continue; // unrecognized option + + // no filtering for encoding (custom encoding for project is allowed) + String value = (String)newOptions.get(key); + preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251) + preferences.setValue(key, value); + } + } + + // persist options + savePreferences(preferences); + } + + /** + * Returns the project custom preference pool. + * Project preferences may include custom encoding. + */ + private Preferences getPreferences() { + Preferences preferences = new Preferences(); + Iterator iter = CModelManager.OptionNames.iterator(); + + while (iter.hasNext()) { + String qualifiedName = (String)iter.next(); + String dequalifiedName = qualifiedName.substring(CCorePlugin.PLUGIN_ID.length()+1); + String value = null; + + try { + value = resource.getPersistentProperty(new QualifiedName(CCorePlugin.PLUGIN_ID, dequalifiedName)); + } catch (CoreException e) { + } + + if (value != null) preferences.setValue(qualifiedName, value); + } + + return preferences; + } + + /** + * Save project custom preferences to persistent properties + */ + private void savePreferences(Preferences preferences) { + if (preferences == null) return; + Iterator iter = CModelManager.OptionNames.iterator(); + + while (iter.hasNext()) { + String qualifiedName = (String)iter.next(); + String dequalifiedName = qualifiedName.substring(CCorePlugin.PLUGIN_ID.length()+1); + String value = null; + + try { + value = preferences.getString(qualifiedName); + + if (value != null && !value.equals(preferences.getDefaultString(qualifiedName))) { + resource.setPersistentProperty(new QualifiedName(CCorePlugin.PLUGIN_ID, dequalifiedName), value); + } else { + resource.setPersistentProperty(new QualifiedName(CCorePlugin.PLUGIN_ID, dequalifiedName), null); + } + } catch (CoreException e) { + } + } + } + + /* + * Set cached preferences, no preferences are saved, only info is updated + */ + private void setPreferences(Preferences preferences) { + // Do nothing + } } diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index dcf548c7843..0412009b09e 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -2,6 +2,11 @@ Update IASTExpression. Move Parser.Backtrack and Parser.EndOfFile to external interface. +2003-06-26 Victor Mozgin + Task tags support in C/C++ comments (initial revision). + Infrastructure to support problem reporting during translation. + Additional infrastructure for options/preferences handling. + 2003-06-25 John Camelon Fixed bug39348 - sizeof elaborated types fail in parsing expression diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java index e5595b272e0..f6cc971ebe1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java @@ -1,19 +1,148 @@ -/********************************************************************** - * Copyright (c) 2002,2003 Rational Software Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * - * Contributors: - * IBM Rational Software - Initial API and implementation -***********************************************************************/ + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ package org.eclipse.cdt.core.parser; - + /** - * @author jcamelon - * + * Description of a C/C++ problem, as detected by the translation or some of the underlying + * technology reusing it. + * A problem provides access to: + * */ -public interface IProblem { +public interface IProblem { + + /** + * Answer back the original arguments recorded into the problem. + * @return the original arguments recorded into the problem + */ + String[] getArguments(); + /** + * Returns the problem id + * + * @return the problem id + */ + int getID(); + + /** + * Answer a localized, human-readable message string which describes the problem. + * + * @return a localized, human-readable message string which describes the problem + */ + String getMessage(); + + /** + * Answer the file name in which the problem was found. + * + * @return the file name in which the problem was found + */ + char[] getOriginatingFileName(); + + /** + * Answer the end position of the problem (inclusive), or -1 if unknown. + * + * @return the end position of the problem (inclusive), or -1 if unknown + */ + int getSourceEnd(); + + /** + * Answer the line number in source where the problem begins. + * + * @return the line number in source where the problem begins + */ + int getSourceLineNumber(); + + /** + * Answer the start position of the problem (inclusive), or -1 if unknown. + * + * @return the start position of the problem (inclusive), or -1 if unknown + */ + int getSourceStart(); + + /** + * Checks the severity to see if the Error bit is set. + * + * @return true if the Error bit is set for the severity, false otherwise + */ + boolean isError(); + + /** + * Checks the severity to see if the Warning bit is not set. + * + * @return true if the Warning bit is not set for the severity, false otherwise + */ + boolean isWarning(); + + /** + * Set the end position of the problem (inclusive), or -1 if unknown. + * Used for shifting problem positions. + * + * @param sourceEnd the given end position + */ + void setSourceEnd(int sourceEnd); + + /** + * Set the line number in source where the problem begins. + * + * @param lineNumber the given line number + */ + void setSourceLineNumber(int lineNumber); + + /** + * Set the start position of the problem (inclusive), or -1 if unknown. + * Used for shifting problem positions. + * + * @param the given start position + */ + void setSourceStart(int sourceStart); + + /** + * Problem Categories + * The high bits of a problem ID contains information about the category of a problem. + * For example, (problemID & TypeRelated) != 0, indicates that this problem is type related. + * + * A problem category can help to implement custom problem filters. Indeed, when numerous problems + * are listed, focusing on import related problems first might be relevant. + * + * When a problem is tagged as Internal, it means that no change other than a local source code change + * can fix the corresponding problem. + */ + int TypeRelated = 0x01000000; + int FieldRelated = 0x02000000; + int MethodRelated = 0x04000000; + int ConstructorRelated = 0x08000000; + int ImportRelated = 0x10000000; + int Internal = 0x20000000; + int Syntax = 0x40000000; + + /** + * Mask to use in order to filter out the category portion of the problem ID. + */ + int IgnoreCategoriesMask = 0xFFFFFF; + + /** + * Below are listed all available problem IDs. Note that this list could be augmented in the future, + * as new features are added to the C/C++ core implementation. + */ + + /** + * ID reserved for referencing an internal error inside the CCorePlugin implementation which + * may be surfaced as a problem associated with the translation unit which caused it to occur. + */ + int Unclassified = 0; + + // detected task + int Task = Internal + 450; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblemReporter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblemReporter.java new file mode 100644 index 00000000000..8dc3e8e0e27 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblemReporter.java @@ -0,0 +1,27 @@ +/* + * Created on 25-Jun-2003 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package org.eclipse.cdt.core.parser; + +/** + * @author vmozgin + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +public interface IProblemReporter { + + public ITranslationOptions getOptions(); + + public abstract void task( + String tag, + String message, + String priority, + int start, + int end, + int line, + ITranslationResult result); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IReferenceContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IReferenceContext.java new file mode 100644 index 00000000000..5bde5620cfd --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IReferenceContext.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.parser; + +/** + * Implementors are valid translation contexts from which we can + * escape in case of error: + * For example: method, type or translation unit. + */ +public interface IReferenceContext { + + ITranslationResult translationResult(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java index 25f36ca4d26..61358e74aad 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java @@ -33,12 +33,9 @@ public interface IScanner { public int getCount(); public int getDepth(); - /** - * @return - */ + public IToken nextTokenForStringizing() throws ScannerException, EndOfFile; - /** - * @param b - */ public void setTokenizingMacroReplacementList(boolean b); + + public void onParseEnd(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerContext.java index 05586936e6f..fb8ce485c84 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerContext.java @@ -24,9 +24,10 @@ public interface IScannerContext { * * @param macroOffset Offset of the expanding macro * @param macroLength Length of the macro identifier + * @param line Initial line counter for the context * @return */ - public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i, int macroOffset, int macroLength); + public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i, int macroOffset, int macroLength, int line); public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i); public int read() throws IOException; @@ -55,7 +56,13 @@ public interface IScannerContext { * @return int */ public int getRelativeOffset(); - + + /** + * Returns current line counter. + * @return int + */ + public int getLine(); + public Reader getReader(); public int undoStackSize(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITranslationOptions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITranslationOptions.java new file mode 100644 index 00000000000..c0b2c11fea7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITranslationOptions.java @@ -0,0 +1,35 @@ +/* + * Created on 25-Jun-2003 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ + +package org.eclipse.cdt.core.parser; + +import java.util.Map; + +/** + * @author vmozgin + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +public interface ITranslationOptions { + + /** + * Option IDs + */ + public static final String OPTION_TaskTags + = "org.eclipse.cdt.core.translation.taskTags"; //$NON-NLS-1$ + public static final String OPTION_TaskPriorities + = "org.eclipse.cdt.core.translation.taskPriorities"; //$NON-NLS-1$ + + /** + * Initializing the compiler options with external settings + */ + public abstract void initialize(Map settings); + + public abstract char[][] getTaskTags(); + public abstract char[][] getTaskPriorities(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITranslationResult.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITranslationResult.java new file mode 100644 index 00000000000..d0fa2cc9884 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITranslationResult.java @@ -0,0 +1,65 @@ +/* + * Created on 25-Jun-2003 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ + +package org.eclipse.cdt.core.parser; + +import org.eclipse.cdt.core.model.ITranslationUnit; + +/** + * @author vmozgin + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ + +public interface ITranslationResult { + + public abstract IProblem[] getAllProblems(); + + /** + * Answer the initial translation unit corresponding to the present translation result + */ + public abstract ITranslationUnit getTranslationUnit(); + + /** + * Answer the initial file name + */ + public abstract char[] getFileName(); + + /** + * Answer the errors encountered during translation. + */ + public abstract IProblem[] getErrors(); + + /** + * Answer the problems (errors and warnings) encountered during translation. + * + * It is intended to be used only once all problems have been detected, + * and makes sure the problems slot as the exact size of the number of + * problems. + */ + public abstract IProblem[] getProblems(); + + /** + * Answer the tasks (TO-DO, ...) encountered during translation. + * + * It is intended to be used only once all problems have been detected, + * and makes sure the problems slot as the exact size of the number of + * problems. + */ + public abstract IProblem[] getTasks(); + + public abstract boolean hasErrors(); + public abstract boolean hasProblems(); + public abstract boolean hasSyntaxError(); + public abstract boolean hasTasks(); + public abstract boolean hasWarnings(); + + public abstract void record(IProblem newProblem, IReferenceContext referenceContext); + + public abstract ITranslationResult tagAsAccepted(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java index 358c178caa9..caab0b47ae0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java @@ -23,6 +23,7 @@ import org.eclipse.cdt.internal.core.parser.Scanner; import org.eclipse.cdt.internal.core.parser.ast.full.FullParseASTFactory; import org.eclipse.cdt.internal.core.parser.ast.quick.QuickParseASTFactory; + /** * @author jcamelon * @@ -37,30 +38,45 @@ public class ParserFactory { return new FullParseASTFactory(); } - public static IParser createParser( IScanner scanner, IParserCallback callback, ParserMode mode ) + public static IParser createParser( IScanner scanner, IParserCallback callback, ParserMode mode ) + { + return createParser(scanner, callback, mode, null, null); + } + + public static IParser createParser( IScanner scanner, IParserCallback callback, ParserMode mode, IProblemReporter problemReporter, ITranslationResult unitResult ) { ParserMode ourMode = ( (mode == null )? ParserMode.COMPLETE_PARSE : mode ); IParserCallback ourCallback = (( callback == null) ? new NullSourceElementRequestor() : callback ); - return new Parser( scanner, ourCallback, ourMode ); + return new Parser( scanner, ourCallback, ourMode, problemReporter, unitResult ); } - - public static IScanner createScanner( Reader input, String fileName, Map defns, List inclusions, ParserMode mode ) + + public static IScanner createScanner( Reader input, String fileName, Map defns, List inclusions, ParserMode mode ) + { + return createScanner(input, fileName, defns, inclusions, mode, null, null); + } + + public static IScanner createScanner( Reader input, String fileName, Map defns, List inclusions, ParserMode mode, IProblemReporter problemReporter, ITranslationResult unitResult ) { ParserMode ourMode = ( (mode == null )? ParserMode.COMPLETE_PARSE : mode ); - IScanner s = new Scanner( input, fileName, defns ); + IScanner s = new Scanner( input, fileName, defns, problemReporter, unitResult ); s.setMode( ourMode ); s.overwriteIncludePath(inclusions); return s; } - - public static IPreprocessor createPreprocessor( Reader input, String fileName, Map defns, List inclusions, ParserMode mode ) + + public static IPreprocessor createPreprocessor( Reader input, String fileName, Map defns, List inclusions, ParserMode mode ) + { + return createPreprocessor(input, fileName, defns, inclusions, mode, null, null); + } + + public static IPreprocessor createPreprocessor( Reader input, String fileName, Map defns, List inclusions, ParserMode mode, IProblemReporter problemReporter, ITranslationResult unitResult ) { ParserMode ourMode = ( (mode == null )? ParserMode.COMPLETE_PARSE : mode ); - IPreprocessor s = new Preprocessor( input, fileName, defns ); + IPreprocessor s = new Preprocessor( input, fileName, defns, problemReporter, unitResult ); s.setMode( ourMode ); s.overwriteIncludePath(inclusions); - return s; - } + return s; + } public static ILineOffsetReconciler createLineOffsetReconciler( Reader input ) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextStack.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextStack.java index f88b29e38d7..54b43177314 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextStack.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextStack.java @@ -42,6 +42,8 @@ public class ContextStack { public void updateContext(Reader reader, String filename, int type, IASTInclusion inclusion, ISourceElementRequestor requestor, int macroOffset, int macroLength) throws ScannerException { + int startLine = 1; + // If we expand a macro within a macro, then keep offsets of the top-level one, // as only the top level macro identifier is properly positioned if (type == IScannerContext.MACROEXPANSION) { @@ -49,10 +51,12 @@ public class ContextStack { macroOffset = currentContext.getMacroOffset(); macroLength = currentContext.getMacroLength(); } + + startLine = currentContext.getLine(); } - + undoStack.clear(); - push( new ScannerContext().initialize(reader, filename, type, null, macroOffset, macroLength ), requestor ); + push( new ScannerContext().initialize(reader, filename, type, null, macroOffset, macroLength, startLine ), requestor ); } protected void push( IScannerContext context, ISourceElementRequestor requestor ) throws ScannerException diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DefaultErrorHandlingPolicies.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DefaultErrorHandlingPolicies.java new file mode 100644 index 00000000000..1decbaaf1ba --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DefaultErrorHandlingPolicies.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser; + +public class DefaultErrorHandlingPolicies { + + /** + * Accumulate all problems, then exit without proceeding. + * + * Typically, the #proceedWithProblems(Problem[]) should + * show the problems. + * + */ + public static IErrorHandlingPolicy exitAfterAllProblems() { + return new IErrorHandlingPolicy() { + public boolean stopOnFirstError() { + return false; + } + public boolean proceedOnErrors(){ + return false; + } + }; + } + + /** + * Exit without proceeding on the first problem wich appears + * to be an error. + * + */ + public static IErrorHandlingPolicy exitOnFirstError() { + return new IErrorHandlingPolicy() { + public boolean stopOnFirstError() { + return true; + } + public boolean proceedOnErrors(){ + return false; + } + }; + } + + /** + * Proceed on the first error met. + * + */ + public static IErrorHandlingPolicy proceedOnFirstError() { + return new IErrorHandlingPolicy() { + public boolean stopOnFirstError() { + return true; + } + public boolean proceedOnErrors(){ + return true; + } + }; + } + + /** + * Accumulate all problems, then proceed with them. + * + */ + public static IErrorHandlingPolicy proceedWithAllProblems() { + return new IErrorHandlingPolicy() { + public boolean stopOnFirstError() { + return false; + } + public boolean proceedOnErrors(){ + return true; + } + }; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IErrorHandlingPolicy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IErrorHandlingPolicy.java new file mode 100644 index 00000000000..66e4fac919e --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IErrorHandlingPolicy.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser; + +/** + * Handler policy is responsible to answer the 2 following + * questions: + * 1. should the handler stop on first problem which appears + * to be a real error (that is, not a warning), + * 2. should it proceed once it has gathered all problems + * + * The intent is that one can supply its own policy to implement + * some interactive error handling strategy where some UI would + * display problems and ask user if he wants to proceed or not. + */ + +public interface IErrorHandlingPolicy { + boolean proceedOnErrors(); + boolean stopOnFirstError(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IProblemFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IProblemFactory.java new file mode 100644 index 00000000000..2cd03216bd3 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IProblemFactory.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser; + +import org.eclipse.cdt.core.parser.IProblem; + +import java.util.Locale; + +/** + * Factory used during translation to build the actual problems + * which are handed back in the translation result. + * + * This allows sharing the internal problem representation with the environment. + * + * Note: The factory is responsible for computing and storing a localized error message. + */ + +public interface IProblemFactory { + + IProblem createProblem( + char[] originatingFileName, + int problemId, + String[] problemArguments, + String[] messageArguments, // shorter versions of the problemArguments + int severity, + int startPosition, + int endPosition, + int lineNumber); + + Locale getLocale(); + + String getLocalizedMessage(int problemId, String[] messageArguments); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ITranslationResultRequestor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ITranslationResultRequestor.java new file mode 100644 index 00000000000..497dbba564d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ITranslationResultRequestor.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser; + +import org.eclipse.cdt.core.parser.ITranslationResult; + +/** + * A callback interface for receiving translation results. + */ +public interface ITranslationResultRequestor { + + /** + * Accept a translation result. + */ + public void acceptResult(ITranslationResult result); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java index 99a82f49a88..9ff44fc00d9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java @@ -13,7 +13,9 @@ import org.eclipse.cdt.core.parser.Backtrack; import org.eclipse.cdt.core.parser.EndOfFile; import org.eclipse.cdt.core.parser.IParser; import org.eclipse.cdt.core.parser.IParserCallback; +import org.eclipse.cdt.core.parser.IProblemReporter; import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.ITranslationResult; import org.eclipse.cdt.core.parser.ISourceElementRequestor; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ParserFactory; @@ -34,6 +36,8 @@ import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier.ClassNameType; import org.eclipse.cdt.internal.core.model.Util; + + /** * This is our first implementation of the IParser interface, serving as a parser for * ANSI C and C++. @@ -57,7 +61,10 @@ public class Parser implements IParser private boolean cppNature = true; // true for C++, false for C private ISourceElementRequestor requestor = null; // new callback mechanism - private IASTFactory astFactory = null; // ast factory + private IASTFactory astFactory = null; // ast factory + + private IProblemReporter problemReporter = null; + private ITranslationResult unitResult = null; /** * This is the single entry point for setting parsePassed to * false, and also making note what token offset we failed upon. @@ -78,10 +85,12 @@ public class Parser implements IParser * @param c IParserCallback instance that will receive callbacks as we parse * @param quick Are we asking for a high level parse or not? */ - public Parser(IScanner s, IParserCallback c, ParserMode m) + public Parser(IScanner s, IParserCallback c, ParserMode m, IProblemReporter problemReporter, ITranslationResult unitResult) { callback = c; scanner = s; + this.problemReporter = problemReporter; + this.unitResult = unitResult; if (c instanceof ISourceElementRequestor) setRequestor((ISourceElementRequestor)c); mode = m; @@ -90,8 +99,11 @@ public class Parser implements IParser scanner.setCallback(c); scanner.setASTFactory(astFactory); } + + // counter that keeps track of the number of times Parser.parse() is called private static int parseCount = 0; - // counter that keeps track of the number of times Parser.parse() is called + + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.IParser#parse() */ @@ -99,6 +111,7 @@ public class Parser implements IParser { long startTime = System.currentTimeMillis(); translationUnit(); + onParseEnd(); // For the debuglog to take place, you have to call // Util.setDebugging(true); // Or set debug to true in the core plugin preference @@ -111,6 +124,11 @@ public class Parser implements IParser + (parsePassed ? "" : " - parse failure")); return parsePassed; } + + public void onParseEnd() { + scanner.onParseEnd(); + } + /** * This is the top-level entry point into the ANSI C++ grammar. * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Preprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Preprocessor.java index cad991c6070..18dd83e0701 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Preprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Preprocessor.java @@ -15,8 +15,11 @@ import java.util.Map; import org.eclipse.cdt.core.parser.EndOfFile; import org.eclipse.cdt.core.parser.IPreprocessor; +import org.eclipse.cdt.core.parser.IProblemReporter; +import org.eclipse.cdt.core.parser.ITranslationResult; import org.eclipse.cdt.core.parser.ScannerException; + /** * @author jcamelon * @@ -28,9 +31,9 @@ public class Preprocessor extends Scanner implements IPreprocessor { * @param filename * @param defns */ - public Preprocessor(Reader reader, String filename, Map defns) { - super(reader, filename, defns); - } + public Preprocessor(Reader reader, String filename, Map defns, IProblemReporter problemReporter, ITranslationResult unitResult) { + super(reader, filename, defns, problemReporter, unitResult); + } public void process() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java index 3469fc46e77..21180b747b0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java @@ -29,10 +29,13 @@ import org.eclipse.cdt.core.parser.EndOfFile; import org.eclipse.cdt.core.parser.IMacroDescriptor; import org.eclipse.cdt.core.parser.IParser; import org.eclipse.cdt.core.parser.IParserCallback; +import org.eclipse.cdt.core.parser.IProblemReporter; import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.core.parser.IScannerContext; import org.eclipse.cdt.core.parser.ISourceElementRequestor; import org.eclipse.cdt.core.parser.IToken; +import org.eclipse.cdt.core.parser.ITranslationResult; +import org.eclipse.cdt.core.parser.ITranslationOptions; import org.eclipse.cdt.core.parser.ParserFactory; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ScannerException; @@ -47,8 +50,8 @@ import org.eclipse.cdt.core.parser.ast.IASTMacro; */ public class Scanner implements IScanner { - - public Scanner(Reader reader, String filename, Map defns) { + + public Scanner(Reader reader, String filename, Map defns, IProblemReporter problemReporter, ITranslationResult unitResult) { try { //this is a hack to get around a sudden EOF experience contextStack.push( @@ -66,6 +69,14 @@ public class Scanner implements IScanner { } if( defns != null ) definitions.putAll( defns ); + + + this.problemReporter = problemReporter; + this.translationResult = unitResult; + + if (problemReporter != null && problemReporter.getOptions() != null) { + this.taskTagsInfo = new TaskTagsInfo(problemReporter.getOptions()); + } } @@ -154,7 +165,7 @@ public class Scanner implements IScanner { int next = getChar(); if (next == '/') { // single line comment - skipOverTextUntilNewline(); + skipOverSinglelineComment(); break; } else if (next == '*') { // multiline comment @@ -497,8 +508,8 @@ public class Scanner implements IScanner { c = getChar(); if( c == '/' ) { - while (c != '\n' && c != NOCHAR) - c = getChar(); + skipOverSinglelineComment(); + c = getChar(); continue; } else if( c == '*' ) @@ -1316,9 +1327,8 @@ public class Scanner implements IScanner { c = getChar(); switch (c) { case '/' : + skipOverSinglelineComment(); c = getChar(); - while (c != '\n' && c != NOCHAR) - c = getChar(); continue; case '*' : skipOverMultilineComment(); @@ -1442,9 +1452,8 @@ public class Scanner implements IScanner { c = getChar(); switch (c) { case '/' : - c = getChar(); - while (c != '\n' && c != NOCHAR) - c = getChar(); + skipOverSinglelineComment(); + c = getChar(); continue; case '*' : skipOverMultilineComment(); @@ -1651,8 +1660,9 @@ public class Scanner implements IScanner { new StringReader(expression + ";"), EXPRESSION, definitions, - null, ParserMode.COMPLETE_PARSE ); - IParser parser = ParserFactory.createParser(trial, evaluator, ParserMode.COMPLETE_PARSE ); + null, ParserMode.COMPLETE_PARSE, + problemReporter, translationResult ); + IParser parser = ParserFactory.createParser(trial, evaluator, ParserMode.COMPLETE_PARSE, problemReporter, translationResult ); parser.expression(null); expressionEvalResult = evaluator.getResult(); @@ -1688,16 +1698,43 @@ public class Scanner implements IScanner { } } } + + protected void skipOverSinglelineComment() throws ScannerException { + + StringBuffer comment = new StringBuffer("//"); + int commentOffset = lastContext.getOffset() - lastContext.undoStackSize() - 2; + int commentStartLine = lastContext.getLine(); + int c; + + loop: + for (;;) { + c = getChar(); + comment.append((char)c); + switch (c) { + case NOCHAR : + case '\n' : + break loop; + default : + break; + } + } + + checkTaskTag(comment, commentOffset, commentStartLine); + } protected boolean skipOverMultilineComment() throws ScannerException { int state = 0; boolean encounteredNewline = false; + StringBuffer comment = new StringBuffer("/*"); + int commentOffset = lastContext.getOffset() - lastContext.undoStackSize() - 2; + int commentStartLine = lastContext.getLine(); // simple state machine to handle multi-line comments // state 0 == no end of comment in site // state 1 == encountered *, expecting / // state 2 == we are no longer in a comment int c = getChar(); + comment.append((char)c); while (state != 2 && c != NOCHAR) { if (c == '\n') encounteredNewline = true; @@ -1715,6 +1752,7 @@ public class Scanner implements IScanner { break; } c = getChar(); + comment.append((char)c); } if (c == NOCHAR) { @@ -1723,6 +1761,8 @@ public class Scanner implements IScanner { } ungetChar(c); + + checkTaskTag(comment, commentOffset, commentStartLine); return encounteredNewline; } @@ -1871,7 +1911,7 @@ public class Scanner implements IScanner { if( ! replacementString.equals( "" ) ) { - IScanner helperScanner = ParserFactory.createScanner( new StringReader(replacementString), null, null, null, mode ); + IScanner helperScanner = ParserFactory.createScanner( new StringReader(replacementString), null, null, null, mode, problemReporter, translationResult ); helperScanner.setTokenizingMacroReplacementList( true ); IToken t = helperScanner.nextToken(false); @@ -1928,7 +1968,7 @@ public class Scanner implements IScanner { c = getChar(); if (c == '/') // one line comment { - skipOverTextUntilNewline(); + skipOverSinglelineComment(); addDefinition(key, ""); } else if (c == '*') // multi-line comment { @@ -1969,7 +2009,7 @@ public class Scanner implements IScanner { protected Vector getMacroParameters (String params, boolean forStringizing) throws ScannerException { - IScanner tokenizer = ParserFactory.createScanner(new StringReader(params), TEXT, definitions, null, mode ); + IScanner tokenizer = ParserFactory.createScanner(new StringReader(params), TEXT, definitions, null, mode, problemReporter, translationResult ); Vector parameterValues = new Vector(); Token t = null; String str = new String(); @@ -2205,5 +2245,171 @@ public class Scanner implements IScanner { */ public void setASTFactory(IASTFactory f) { astFactory = f; - } + } + + // task tag support + private class TaskTagsInfo { + char[][] taskTags = null; + char[][] taskPriorities = null; + + class FoundTaskInfo { + char[] foundTaskTags = null; + char[] foundTaskMessages = null; + char[] foundTaskPriorities = null; + int foundTaskStartOffset = -1; + int foundTaskEndOffset = -1; + int foundTaskLine = -1; + }; + + FoundTaskInfo[] foundTaskInfo = null; + int foundTaskCount = 0; + + TaskTagsInfo(ITranslationOptions options) { + this.taskTags = options.getTaskTags(); + this.taskPriorities = options.getTaskPriorities(); + } + } + + IProblemReporter problemReporter = null; + ITranslationResult translationResult = null; + TaskTagsInfo taskTagsInfo = null; + + + // check presence of task tags + public void checkTaskTag(StringBuffer comment, int commentStart, int commentStartLine) { + + if (this.taskTagsInfo == null) return; + + int commentLength = comment.length(); + int tagStartLine = commentStartLine; + int foundTaskIndex = taskTagsInfo.foundTaskCount; + char[][] taskTags = taskTagsInfo.taskTags; + char[][] taskPriorities = taskTagsInfo.taskPriorities; + + // only look for newer task tags + if (foundTaskIndex > 0) { + TaskTagsInfo.FoundTaskInfo lastInfo = taskTagsInfo.foundTaskInfo[foundTaskIndex-1]; + + if (lastInfo.foundTaskStartOffset >= commentStart) + return; + } + + nextChar: + for (int i = 0; i < commentLength; i++) { + if (comment.charAt(i) == '\n') tagStartLine++; + + int nextPos = -1; + char[] tag = null; + char[] priority = null; + int tagLength = 0; + + // check for tag occurrence + nextTag: + for (int itag = 0; itag < taskTags.length; itag++) { + tag = taskTags[itag]; + tagLength = tag.length; + priority = (taskPriorities != null && itag < taskPriorities.length) + ? taskPriorities[itag] + : null; + + for (int t = 0; t < tagLength; t++){ + if (comment.charAt(i+t) != tag[t]) continue nextTag; + } + nextPos = i + tagLength; + + int fTC = taskTagsInfo.foundTaskCount; + + if (taskTagsInfo.foundTaskInfo == null) { + taskTagsInfo.foundTaskInfo = new TaskTagsInfo.FoundTaskInfo[5]; + } else if (fTC == taskTagsInfo.foundTaskInfo.length) { + TaskTagsInfo.FoundTaskInfo[] resizedFTI = new TaskTagsInfo.FoundTaskInfo[fTC*2]; + System.arraycopy(taskTagsInfo.foundTaskInfo, 0, resizedFTI, 0, fTC); + } + + TaskTagsInfo.FoundTaskInfo lastFTI = taskTagsInfo.new FoundTaskInfo(); + + lastFTI.foundTaskTags = tag; + lastFTI.foundTaskPriorities = priority; + lastFTI.foundTaskStartOffset = i; + lastFTI.foundTaskLine = tagStartLine; + + taskTagsInfo.foundTaskInfo[fTC] = lastFTI; + taskTagsInfo.foundTaskCount++; + + for (int jj=i+1; jj= msgStart; j--){ + if ((c = comment.charAt(j)) == '*') { + end = j-1; + break; + } + } + if (end < 0) end = commentLength-1; + } + + // trim the message + while (Character.isWhitespace(comment.charAt(end)) && msgStart <= end) end--; + while (Character.isWhitespace(comment.charAt(msgStart)) && msgStart <= end) msgStart++; + + // update the end position of the task + fTI.foundTaskEndOffset = end; + + // get the message source + final int messageLength = end-msgStart+1; + char[] message = new char[messageLength]; + + comment.getChars(msgStart, msgStart + messageLength, message, 0); + fTI.foundTaskMessages = message; + + fTI.foundTaskStartOffset += commentStart; + fTI.foundTaskEndOffset += commentStart; + } + } + + + public void onParseEnd() { + if (problemReporter != null && taskTagsInfo != null){ + for (int i = 0; i < taskTagsInfo.foundTaskCount; i++) { + TaskTagsInfo.FoundTaskInfo fTI = taskTagsInfo.foundTaskInfo[i]; + + problemReporter.task( + new String(fTI.foundTaskTags), + new String(fTI.foundTaskMessages), + fTI.foundTaskPriorities == null ? null : new String(fTI.foundTaskPriorities), + fTI.foundTaskStartOffset, + fTI.foundTaskEndOffset, + fTI.foundTaskLine, + this.translationResult); + } + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java index 2c26bb0a672..ea037d41a8d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java @@ -23,6 +23,7 @@ public class ScannerContext implements IScannerContext private String filename; private int macroOffset = -1; private int macroLength = -1; + private int line = 1; private int offset; private Stack undo = new Stack(); private int kind; @@ -30,9 +31,9 @@ public class ScannerContext implements IScannerContext public ScannerContext(){} /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.IScannerContext#initialize(Reader, String, int, IASTInclusion, int, int) + * @see org.eclipse.cdt.internal.core.parser.IScannerContext#initialize(Reader, String, int, IASTInclusion, int, int, int) */ - public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i, int mO, int mL) + public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i, int mO, int mL, int l) { reader = r; filename = f; @@ -41,6 +42,7 @@ public class ScannerContext implements IScannerContext inc = i; macroOffset = mO; macroLength = mL; + line = l; return this; } @@ -49,12 +51,14 @@ public class ScannerContext implements IScannerContext */ public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i) { - return initialize(r, f, k, i, -1, -1); + return initialize(r, f, k, i, -1, -1, 1); } public int read() throws IOException { ++offset; - return reader.read(); + int c = reader.read(); + if ((char)c == '\n') line++; + return c; } /** @@ -99,6 +103,14 @@ public class ScannerContext implements IScannerContext { return offset; } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.IScannerContext#getLine() + */ + public final int getLine() + { + return line; + } /** * Returns the reader. @@ -120,7 +132,9 @@ public class ScannerContext implements IScannerContext */ public final int popUndo() { - return ((Integer)undo.pop()).intValue(); + int c = ((Integer)undo.pop()).intValue(); + if ((char)c == '\n') line++; + return c; } /** @@ -129,6 +143,7 @@ public class ScannerContext implements IScannerContext */ public void pushUndo(int undo) { + if ((char)undo == '\n') line--; this.undo.push( new Integer( undo )); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/TranslationOptions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/TranslationOptions.java new file mode 100644 index 00000000000..539aabe0189 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/TranslationOptions.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser; + +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.cdt.core.parser.ITranslationOptions; + + +public class TranslationOptions implements ITranslationOptions { + + // tags used to recognize tasks in comments + private char[][] taskTags = null; + + // priorities of tasks in comments + private char[][] taskPriorities = null; + + public TranslationOptions(Map settings) { + initialize(settings); + } + + /** + * Initializing the translation options with external settings + */ + public void initialize(Map settings){ + + if (settings == null) return; + + // filter out related options + Iterator entries = settings.entrySet().iterator(); + + while (entries.hasNext()) { + Map.Entry entry = (Map.Entry)entries.next(); + Object oKey = entry.getKey(); + Object oValue = entry.getValue(); + if (!(oKey instanceof String)) continue; + if (!(oValue instanceof String)) continue; + + String optionID = (String) oKey; + String optionValue = (String) oValue; + + // Unpack task tags + if (optionID.equals(OPTION_TaskTags)) { + + if (optionValue.length() == 0) { + this.taskTags = null; + } else { + StringTokenizer tokenizer = new StringTokenizer(optionValue, ","); + this.taskTags = new char[tokenizer.countTokens()][]; + int i = 0; + + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken().trim(); + this.taskTags[i] = token.toCharArray(); + i++; + } + } + + continue; + } + + // Unpack task priorities + if (optionID.equals(OPTION_TaskPriorities)){ + + if (optionValue.length() == 0) { + this.taskPriorities = null; + } else { + StringTokenizer tokenizer = new StringTokenizer(optionValue, ","); + this.taskPriorities = new char[tokenizer.countTokens()][]; + int i = 0; + + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken().trim(); + this.taskPriorities[i] = token.toCharArray(); + i++; + } + } + + continue; + } + } + } + + + public void setTaskTags(char[][] taskTags) { + this.taskTags = taskTags; + } + + public char[][] getTaskTags() { + return taskTags; + } + + public void setTaskPriorities(char[][] taskPriorities) { + this.taskPriorities = taskPriorities; + } + + public char[][] getTaskPriorities() { + return taskPriorities; + } + + + public String toString() { + + StringBuffer buf = new StringBuffer("TranslationOptions:"); //$NON-NLS-1$ + String result = ""; + + if (this.taskTags != null) { + for (int i=0; i + *
  • the translation unit that was processed + *
  • any problems (errors, warnings, tasks etc.) produced + * + */ + +import org.eclipse.cdt.core.parser.*; +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.model.ITranslationUnit; + +public class TranslationResult implements ITranslationResult { + + public IProblem problems[]; + public IProblem tasks[]; + public int problemCount; + public int taskCount; + public ITranslationUnit translationUnit; + private int maxProblemPerUnit; + + public int unitIndex, totalUnitsKnown; + public boolean hasBeenAccepted = false; + public char[] fileName; + + public TranslationResult( + char[] fileName, + int unitIndex, + int totalUnitsKnown, + int maxProblemPerUnit){ + + this.fileName = fileName; + this.unitIndex = unitIndex; + this.totalUnitsKnown = totalUnitsKnown; + this.maxProblemPerUnit = maxProblemPerUnit; + } + + public static final int DEFAULT_MAX_PROBLEMS_PER_UNIT = 100; + + public TranslationResult( + ITranslationUnit translationUnit) { + this(translationUnit, 1, 1, DEFAULT_MAX_PROBLEMS_PER_UNIT); + } + + public TranslationResult( + ITranslationUnit translationUnit, + int unitIndex, + int totalUnitsKnown, + int maxProblemPerUnit){ + + this.fileName = translationUnit.getPath().lastSegment().toCharArray(); + this.translationUnit = translationUnit; + this.unitIndex = unitIndex; + this.totalUnitsKnown = totalUnitsKnown; + this.maxProblemPerUnit = maxProblemPerUnit; + } + + + private int computePriority(IProblem problem) { + + // early problems first + int priority = 100000 - problem.getSourceLineNumber(); + + return priority; + } + + + public IProblem[] getAllProblems() { + + IProblem[] problems = this.getProblems(); + int problemCount = problems != null ? problems.length : 0; + + IProblem[] tasks = this.getTasks(); + int taskCount = tasks != null ? tasks.length : 0; + + if (taskCount == 0) { + return problems; + } + if (problemCount == 0) { + return tasks; + } + + int totalNumberOfProblem = problemCount + taskCount; + IProblem[] allProblems = new IProblem[totalNumberOfProblem]; + + int allProblemIndex = 0; + int taskIndex = 0; + int problemIndex = 0; + + while (taskIndex + problemIndex < totalNumberOfProblem) { + IProblem nextTask = null; + IProblem nextProblem = null; + + if (taskIndex < taskCount) { + nextTask = tasks[taskIndex]; + } + if (problemIndex < problemCount) { + nextProblem = problems[problemIndex]; + } + + // select the next problem + IProblem currentProblem = null; + if (nextProblem != null) { + if (nextTask != null) { + if (nextProblem.getSourceStart() < nextTask.getSourceStart()) { + currentProblem = nextProblem; + problemIndex++; + } else { + currentProblem = nextTask; + taskIndex++; + } + } else { + currentProblem = nextProblem; + problemIndex++; + } + } else { + if (nextTask != null) { + currentProblem = nextTask; + taskIndex++; + } + } + allProblems[allProblemIndex++] = currentProblem; + } + + return allProblems; + } + + /** + * Answer the initial translation unit corresponding to the present translation result + */ + public ITranslationUnit getTranslationUnit() { + return translationUnit; + } + + /** + * Answer the initial file name + */ + public char[] getFileName() { + return fileName; + } + + /** + * Answer the errors encountered during translation. + */ + public IProblem[] getErrors() { + + IProblem[] problems = getProblems(); + int errorCount = 0; + + for (int i = 0; i < this.problemCount; i++) { + if (problems[i].isError()) errorCount++; + } + if (errorCount == this.problemCount) return problems; + + IProblem[] errors = new IProblem[errorCount]; + int index = 0; + + for (int i = 0; i < this.problemCount; i++) { + if (problems[i].isError()) errors[index++] = problems[i]; + } + return errors; + } + + /** + * Answer the problems (errors and warnings) encountered during translation. + * + * This is not a compiler internal API - it has side-effects ! + * It is intended to be used only once all problems have been detected, + * and makes sure the problems slot as the exact size of the number of + * problems. + */ + public IProblem[] getProblems() { + + // Re-adjust the size of the problems if necessary. + if (problems != null) { + + if (this.problemCount != problems.length) { + System.arraycopy(problems, 0, (problems = new IProblem[problemCount]), 0, problemCount); + } + + if (this.maxProblemPerUnit > 0 && this.problemCount > this.maxProblemPerUnit){ + quickPrioritize(problems, 0, problemCount - 1); + this.problemCount = this.maxProblemPerUnit; + System.arraycopy(problems, 0, (problems = new IProblem[problemCount]), 0, problemCount); + } + + // Sort problems per source positions. + quickSort(problems, 0, problems.length-1); + } + return problems; + } + + /** + * Answer the tasks (TO-DO, ...) encountered during translation. + * + * This is not a compiler internal API - it has side-effects ! + * It is intended to be used only once all problems have been detected, + * and makes sure the problems slot as the exact size of the number of + * problems. + */ + public IProblem[] getTasks() { + + // Re-adjust the size of the tasks if necessary. + if (this.tasks != null) { + + if (this.taskCount != this.tasks.length) { + System.arraycopy(this.tasks, 0, (this.tasks = new IProblem[this.taskCount]), 0, this.taskCount); + } + quickSort(tasks, 0, tasks.length-1); + } + return this.tasks; + } + + public boolean hasErrors() { + + if (problems != null) + for (int i = 0; i < problemCount; i++) { + if (problems[i].isError()) + return true; + } + return false; + } + + public boolean hasProblems() { + + return problemCount != 0; + } + + public boolean hasSyntaxError(){ + + if (problems != null) + for (int i = 0; i < problemCount; i++) { + IProblem problem = problems[i]; + if ((problem.getID() & IProblem.Syntax) != 0 && problem.isError()) + return true; + } + return false; + } + + public boolean hasTasks() { + return this.taskCount != 0; + } + + public boolean hasWarnings() { + + if (problems != null) + for (int i = 0; i < problemCount; i++) { + if (problems[i].isWarning()) + return true; + } + return false; + } + + private static void quickSort(IProblem[] list, int left, int right) { + + if (left >= right) return; + + // sort the problems by their source start position... starting with 0 + int original_left = left; + int original_right = right; + int mid = list[(left + right) / 2].getSourceStart(); + + do { + while (list[left].getSourceStart() < mid) + left++; + + while (mid < list[right].getSourceStart()) + right--; + + if (left <= right) { + IProblem tmp = list[left]; + list[left] = list[right]; + list[right] = tmp; + left++; + right--; + } + } while (left <= right); + + if (original_left < right) + quickSort(list, original_left, right); + + if (left < original_right) + quickSort(list, left, original_right); + } + + private void quickPrioritize(IProblem[] list, int left, int right) { + + if (left >= right) return; + + // sort the problems by their priority... starting with the highest priority + int original_left = left; + int original_right = right; + int mid = computePriority(list[(left + right) / 2]); + + do { + while (computePriority(list[right]) < mid) + right--; + + while (mid < computePriority(list[left])) + left++; + + if (left <= right) { + IProblem tmp = list[left]; + list[left] = list[right]; + list[right] = tmp; + left++; + right--; + } + } while (left <= right); + + if (original_left < right) + quickPrioritize(list, original_left, right); + + if (left < original_right) + quickPrioritize(list, left, original_right); + } + + + public void record(IProblem newProblem, IReferenceContext referenceContext) { + + if (newProblem.getID() == IProblem.Task) { + recordTask(newProblem); + return; + } + + if (problemCount == 0) { + problems = new IProblem[5]; + } else if (problemCount == problems.length) { + System.arraycopy(problems, 0, (problems = new IProblem[problemCount * 2]), 0, problemCount); + } + + problems[problemCount++] = newProblem; + } + + + private void recordTask(IProblem newProblem) { + if (this.taskCount == 0) { + this.tasks = new IProblem[5]; + } else if (this.taskCount == this.tasks.length) { + System.arraycopy(this.tasks, 0, (this.tasks = new IProblem[this.taskCount * 2]), 0, this.taskCount); + } + + this.tasks[this.taskCount++] = newProblem; + } + + + public ITranslationResult tagAsAccepted() { + this.hasBeenAccepted = true; + return this; + } + + + public String toString() { + + StringBuffer buffer = new StringBuffer(); + if (this.fileName != null){ + buffer.append("Filename : ").append(this.fileName).append('\n'); //$NON-NLS-1$ + } + if (problems != null){ + buffer.append(this.problemCount).append(" PROBLEM(s) detected \n"); //$NON-NLS-1$//$NON-NLS-2$ + for (int i = 0; i < this.problemCount; i++){ + buffer.append("\t - ").append(this.problems[i]).append('\n'); //$NON-NLS-1$ + } + } else { + buffer.append("No PROBLEM\n"); //$NON-NLS-1$ + } + return buffer.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/DefaultProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/DefaultProblem.java new file mode 100644 index 00000000000..ff95768df78 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/DefaultProblem.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.problem; + +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.parser.IProblem; + + +public class DefaultProblem implements IProblem { + + private char[] fileName; + private int id; + private int startPosition, endPosition, line; + private int severity; + private String[] arguments; + private String message; + + public DefaultProblem( + char[] originatingFileName, + String message, + int id, + String[] stringArguments, + int severity, + int startPosition, + int endPosition, + int line) { + + this.fileName = originatingFileName; + this.message = message; + this.id = id; + this.arguments = stringArguments; + this.severity = severity; + this.startPosition = startPosition; + this.endPosition = endPosition; + this.line = line; + } + + public String errorReportSource(ITranslationUnit translationUnit) { + //extra from the source the innacurate token + //and "highlight" it using some underneath ^^^^^ + //put some context around too. + + //this code assumes that the font used in the console is fixed size + + //sanity ..... + if ((startPosition > endPosition) + || ((startPosition <= 0) && (endPosition <= 0))) + return "\n!! no source information available !!"; + + final char SPACE = '\u0020'; + final char MARK = '^'; + final char TAB = '\t'; + char[] source = translationUnit.getContents(); + //the next code tries to underline the token..... + //it assumes (for a good display) that token source does not + //contain any \r \n. This is false on statements ! + //(the code still works but the display is not optimal !) + + //compute the how-much-char we are displaying around the inaccurate token + int begin = startPosition >= source.length ? source.length - 1 : startPosition; + int relativeStart = 0; + int end = endPosition >= source.length ? source.length - 1 : endPosition; + int relativeEnd = 0; + label : for (relativeStart = 0;; relativeStart++) { + if (begin == 0) + break label; + if ((source[begin - 1] == '\n') || (source[begin - 1] == '\r')) + break label; + begin--; + } + label : for (relativeEnd = 0;; relativeEnd++) { + if ((end + 1) >= source.length) + break label; + if ((source[end + 1] == '\r') || (source[end + 1] == '\n')) { + break label; + } + end++; + } + //extract the message form the source + char[] extract = new char[end - begin + 1]; + System.arraycopy(source, begin, extract, 0, extract.length); + char c; + //remove all SPACE and TAB that begin the error message... + int trimLeftIndex = 0; + while (((c = extract[trimLeftIndex++]) == TAB) || (c == SPACE)) { + }; + System.arraycopy( + extract, + trimLeftIndex - 1, + extract = new char[extract.length - trimLeftIndex + 1], + 0, + extract.length); + relativeStart -= trimLeftIndex; + //buffer spaces and tabs in order to reach the error position + int pos = 0; + char[] underneath = new char[extract.length]; // can't be bigger + for (int i = 0; i <= relativeStart; i++) { + if (extract[i] == TAB) { + underneath[pos++] = TAB; + } else { + underneath[pos++] = SPACE; + } + } + //mark the error position + for (int i = startPosition; + i <= (endPosition >= source.length ? source.length - 1 : endPosition); + i++) + underneath[pos++] = MARK; + //resize underneathto remove 'null' chars + System.arraycopy(underneath, 0, underneath = new char[pos], 0, pos); + + return " at line" + String.valueOf(line) + + "\n\t" + new String(extract) + "\n\t" + new String(underneath); //$NON-NLS-2$ //$NON-NLS-1$ + } + + /** + * Answer back the original arguments recorded into the problem. + * @return java.lang.String[] + */ + public String[] getArguments() { + + return arguments; + } + + /** + * Answer the type of problem. + * @see org.eclipse.cdt.core.parser.IProblem#getID() + * @return int + */ + public int getID() { + + return id; + } + + /** + * Answer a localized, human-readable message string which describes the problem. + * @return java.lang.String + */ + public String getMessage() { + + return message; + } + + /** + * Answer the file name in which the problem was found. + * @return char[] + */ + public char[] getOriginatingFileName() { + + return fileName; + } + + /** + * Answer the end position of the problem (inclusive), or -1 if unknown. + * @return int + */ + public int getSourceEnd() { + + return endPosition; + } + + /** + * Answer the line number in source where the problem begins. + * @return int + */ + public int getSourceLineNumber() { + + return line; + } + + /** + * Answer the start position of the problem (inclusive), or -1 if unknown. + * @return int + */ + public int getSourceStart() { + + return startPosition; + } + + /* + * Helper method: checks the severity to see if the Error bit is set. + * @return boolean + */ + public boolean isError() { + + return (severity & IProblemSeverities.Error) != 0; + } + + /* + * Helper method: checks the severity to see if the Warning bit is set. + * @return boolean + */ + public boolean isWarning() { + + return (severity & IProblemSeverities.Warning) == 0; + } + + /** + * Set the end position of the problem (inclusive), or -1 if unknown. + * + * Used for shifting problem positions. + * @param sourceEnd the new value of the sourceEnd of the receiver + */ + public void setSourceEnd(int sourceEnd) { + + endPosition = sourceEnd; + } + + /** + * Set the line number in source where the problem begins. + * @param lineNumber the new value of the line number of the receiver + */ + public void setSourceLineNumber(int lineNumber) { + + line = lineNumber; + } + + /** + * Set the start position of the problem (inclusive), or -1 if unknown. + * + * Used for shifting problem positions. + * @param sourceStart the new value of the source start position of the receiver + */ + public void setSourceStart(int sourceStart) { + + startPosition = sourceStart; + } + + public String toString() { + + String s = "Pb(" + (id & IgnoreCategoriesMask) + ") "; //$NON-NLS-1$ //$NON-NLS-2$ + if (message != null) { + s += message; + } else { + if (arguments != null) + for (int i = 0; i < arguments.length; i++) + s += " " + arguments[i]; //$NON-NLS-1$ + } + return s; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/DefaultProblemFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/DefaultProblemFactory.java new file mode 100644 index 00000000000..1d814534b67 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/DefaultProblemFactory.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.problem; + +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.internal.core.parser.IProblemFactory; + + +public class DefaultProblemFactory implements IProblemFactory { + + public String[] messageTemplates; + private Locale locale; + private static String[] DEFAULT_LOCALE_TEMPLATES; + private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ + private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ + + /** + * @param loc the locale used to get the right message + */ + public DefaultProblemFactory(Locale loc) { + this.locale = loc; + if (Locale.getDefault().equals(loc)){ + if (DEFAULT_LOCALE_TEMPLATES == null){ + DEFAULT_LOCALE_TEMPLATES = loadMessageTemplates(loc); + } + this.messageTemplates = DEFAULT_LOCALE_TEMPLATES; + } else { + this.messageTemplates = loadMessageTemplates(loc); + } + } + + /** + * Answer a new IProblem created according to the parameters value + *
      + *
    • originatingFileName the name of the file name from which the problem is originated + *
    • problemId the problem id + *
    • problemArguments the fully qualified arguments recorded inside the problem + *
    • messageArguments the arguments needed to set the error message (shorter names than problemArguments ones) + *
    • severity the severity of the problem + *
    • startPosition the starting position of the problem + *
    • endPosition the end position of the problem + *
    • lineNumber the line on which the problem occured + *
    + * @param originatingFileName char[] + * @param problemId int + * @param arguments String[] + * @param severity int + * @param startPosition int + * @param endPosition int + * @param lineNumber int + * @return org.eclipse.cdt.core.parser.IProblem + */ + public IProblem createProblem( + char[] originatingFileName, + int problemId, + String[] problemArguments, + String[] messageArguments, + int severity, + int startPosition, + int endPosition, + int lineNumber) { + + return new DefaultProblem( + originatingFileName, + this.getLocalizedMessage(problemId, messageArguments), + problemId, + problemArguments, + severity, + startPosition, + endPosition, + lineNumber); + } + + /** + * Answer the locale used to retrieve the error messages + * @return java.util.Locale + */ + public Locale getLocale() { + return locale; + } + public final String getLocalizedMessage(int id, String[] problemArguments) { + StringBuffer output = new StringBuffer(80); + String message = + messageTemplates[(id & IProblem.IgnoreCategoriesMask)]; + if (message == null) { + return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$ + + (id & IProblem.IgnoreCategoriesMask) + + ". Check translation resources."; //$NON-NLS-1$ + } + + // for compatibility with MessageFormat which eliminates double quotes in original message + message = message.replace('\"', '\''); + + int length = message.length(); + int start = -1, end = length; + while (true) { + if ((end = message.indexOf('{', start)) > -1) { + output.append(message.substring(start + 1, end)); + if ((start = message.indexOf('}', end)) > -1) { + try { + output.append( + problemArguments[Integer.parseInt(message.substring(end + 1, start))]); + } catch (NumberFormatException nfe) { + output.append(message.substring(end + 1, start + 1)); + } catch (ArrayIndexOutOfBoundsException e) { + return "Corrupted translation resources for problem id: " //$NON-NLS-1$ + + (id & IProblem.IgnoreCategoriesMask) + + ". Check translation resources."; //$NON-NLS-1$ + } + } else { + output.append(message.substring(end, length)); + break; + } + } else { + output.append(message.substring(start + 1, length)); + break; + } + } + return output.toString(); + } + + /** + * @param problem org.eclipse.cdt.core.parser.IProblem + * @return String + */ + public final String localizedMessage(IProblem problem) { + return getLocalizedMessage(problem.getID(), problem.getArguments()); + } + + /** + * This method initializes the MessageTemplates class variable according + * to the current Locale. + */ + public static String[] loadMessageTemplates(Locale loc) { + ResourceBundle bundle = null; + String bundleName = "org.eclipse.cdt.internal.core.parser.problem.messages"; //$NON-NLS-1$ + try { + bundle = ResourceBundle.getBundle(bundleName, loc); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + loc); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + String[] templates = new String[500]; + for (int i = 0, max = templates.length; i < max; i++) { + try { + templates[i] = bundle.getString(String.valueOf(i)); + } catch (MissingResourceException e) { + // available ID + } + } + return templates; + } + + public DefaultProblemFactory() { + this(Locale.getDefault()); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/IProblemSeverities.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/IProblemSeverities.java new file mode 100644 index 00000000000..1bff044b2ea --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/IProblemSeverities.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.problem; + +public interface IProblemSeverities { + + final int Ignore = -1; + + final int Error = 0x00001; + final int Warning = 0x00002; + + final int Task = 0x10000; // when bit is set: the problem is a task +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/ProblemHandler.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/ProblemHandler.java new file mode 100644 index 00000000000..5fe4d1f52f6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/ProblemHandler.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.problem; + +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.parser.IReferenceContext; +import org.eclipse.cdt.core.parser.ITranslationOptions; +import org.eclipse.cdt.core.parser.ITranslationResult; +import org.eclipse.cdt.internal.core.parser.IErrorHandlingPolicy; +import org.eclipse.cdt.internal.core.parser.IProblemFactory; + + +/* + * Translation problem handler, responsible to determine whether + * a problem is actually a warning or an error (or a task); also will + * decide whether the translation task can be processed further or not. + * + * Behavior : will request its current policy if need to stop on + * first error, and if should proceed (persist) with problems. + */ + +public class ProblemHandler { + + public final static String[] NoArgument = new String[0]; + + final public IErrorHandlingPolicy policy; + public final IProblemFactory problemFactory; + private final ITranslationOptions options; + + + /** + * Problem handler can be supplied with a policy to specify + * its behavior in error handling. Also see static methods for + * built-in policies. + * + */ + public ProblemHandler(IErrorHandlingPolicy policy, ITranslationOptions options, IProblemFactory problemFactory) { + this.policy = policy; + this.problemFactory = problemFactory; + this.options = options; + } + + + /** + * Given the current configuration, answers which category the problem + * falls into: + * Error | Warning | Ignore | Task + */ + public int computeSeverity(int problemId) { + if (problemId == IProblem.Task) return IProblemSeverities.Task; + + // by default all problems are errors + return IProblemSeverities.Error; + } + + + public IProblem createProblem( + char[] fileName, + int problemId, + String[] problemArguments, + String[] messageArguments, + int severity, + int problemStartPosition, + int problemEndPosition, + int lineNumber, + IReferenceContext referenceContext, + ITranslationResult unitResult) { + + return problemFactory.createProblem( + fileName, + problemId, + problemArguments, + messageArguments, + severity, + problemStartPosition, + problemEndPosition, + lineNumber); + } + + + public void handle( + int problemId, + String[] problemArguments, + String[] messageArguments, + int severity, + int problemStartPosition, + int problemEndPosition, + int line, + IReferenceContext referenceContext, + ITranslationResult unitResult) { + + if (severity == IProblemSeverities.Ignore) + return; + + IProblem problem = + this.createProblem( + unitResult.getFileName(), + problemId, + problemArguments, + messageArguments, + severity, + problemStartPosition, + problemEndPosition, + line >= 0 + ? line + : 1, + referenceContext, + unitResult); + if (problem == null) return; // problem couldn't be created, ignore + + this.record(problem, unitResult, referenceContext); + } + + + /** + * Standard problem handling API, the actual severity (warning/error/ignore) is deducted + * from the problem ID and the current translation options. + */ + public void handle( + int problemId, + String[] problemArguments, + String[] messageArguments, + int problemStartPosition, + int problemEndPosition, + int line, + IReferenceContext referenceContext, + ITranslationResult unitResult) { + + this.handle( + problemId, + problemArguments, + messageArguments, + this.computeSeverity(problemId), // severity inferred using the ID + problemStartPosition, + problemEndPosition, + line, + referenceContext, + unitResult); + } + + + public void record(IProblem problem, ITranslationResult unitResult, IReferenceContext referenceContext) { + unitResult.record(problem, referenceContext); + } + + public ITranslationOptions getOptions() { + return options; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/ProblemReporter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/ProblemReporter.java new file mode 100644 index 00000000000..e65ba665d9f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/ProblemReporter.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.problem; + +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.parser.IProblemReporter; +import org.eclipse.cdt.core.parser.IReferenceContext; +import org.eclipse.cdt.core.parser.ITranslationOptions; +import org.eclipse.cdt.core.parser.ITranslationResult; +import org.eclipse.cdt.internal.core.parser.IErrorHandlingPolicy; +import org.eclipse.cdt.internal.core.parser.IProblemFactory; + + +public class ProblemReporter extends ProblemHandler implements IProblemReporter { + + public IReferenceContext referenceContext = null; + + public ProblemReporter(IErrorHandlingPolicy policy, ITranslationOptions options, IProblemFactory problemFactory) { + super(policy, options, problemFactory); + } + + public void task(String tag, String message, String priority, int start, int end, int line, ITranslationResult result){ + this.handle( + IProblem.Task, + new String[] { tag, message, priority/*secret argument that is not surfaced in getMessage()*/}, + new String[] { tag, message, priority/*secret argument that is not surfaced in getMessage()*/}, + start, + end, + line, + result); + } + + // use this private API when the translation unit result can be found through the + // reference context. Otherwise, use the other API taking a problem and a translation result + // as arguments + private void handle( + int problemId, + String[] problemArguments, + String[] messageArguments, + int problemStartPosition, + int problemEndPosition, + int line){ + + this.handle( + problemId, + problemArguments, + messageArguments, + problemStartPosition, + problemEndPosition, + line, + referenceContext, + referenceContext == null ? null : referenceContext.translationResult()); + referenceContext = null; + } + + // use this private API when the translation unit result can be found through the + // reference context. Otherwise, use the other API taking a problem and a translation result + // as arguments + private void handle( + int problemId, + String[] problemArguments, + String[] messageArguments, + int severity, + int problemStartPosition, + int problemEndPosition, + int line){ + + this.handle( + problemId, + problemArguments, + messageArguments, + severity, + problemStartPosition, + problemEndPosition, + referenceContext, + referenceContext == null ? null : referenceContext.translationResult()); + referenceContext = null; + } + + // use this private API when the translation unit result cannot be found through the + // reference context. + private void handle( + int problemId, + String[] problemArguments, + String[] messageArguments, + int problemStartPosition, + int problemEndPosition, + int line, + ITranslationResult unitResult){ + + this.handle( + problemId, + problemArguments, + messageArguments, + problemStartPosition, + problemEndPosition, + line, + referenceContext, + unitResult); + referenceContext = null; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/messages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/messages.properties new file mode 100644 index 00000000000..89158b26e84 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/messages.properties @@ -0,0 +1,14 @@ +############################################################################### +# Copyright (c) 2000, 2003 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Common Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/cpl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +0 = {0} + +# Task message: {taskTag} {taskMessage} +450 = {0} {1} diff --git a/core/org.eclipse.cdt.core/plugin.properties b/core/org.eclipse.cdt.core/plugin.properties index 53b857f2830..40e3064f0cf 100644 --- a/core/org.eclipse.cdt.core/plugin.properties +++ b/core/org.eclipse.cdt.core/plugin.properties @@ -18,3 +18,5 @@ makebuildmodel.name=Make Builder ManagedBuildNature.name=Managed C/C++ Build Nature GeneratedMakefileCBuilder.name=Generated Makefile C/C++ Builder + +CTaskName=C/C++ Task diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index 8556b54f880..7fcd93752b1 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -280,4 +280,9 @@ + + + + + diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index f190526499c..b92011474c7 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -8,12 +8,16 @@ package org.eclipse.cdt.core; import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Iterator; import org.eclipse.cdt.core.index.IndexModel; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.resources.IConsole; import org.eclipse.cdt.internal.core.CDescriptorManager; import org.eclipse.cdt.internal.core.CPathEntry; +import org.eclipse.cdt.internal.core.model.CModelManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IWorkspace; @@ -29,6 +33,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; @@ -47,6 +52,47 @@ public class CCorePlugin extends Plugin { public final static String DEFAULT_BINARY_PARSER_SIMPLE_ID = "ELF"; public final static String DEFAULT_BINARY_PARSER_UNIQ_ID = PLUGIN_ID + "." + DEFAULT_BINARY_PARSER_SIMPLE_ID; public final static String PREF_USE_NEW_PARSER = "useNewParser"; + + /** + * Possible configurable option ID. + * @see #getDefaultOptions + */ + public static final String TRANSLATION_TASK_PRIORITIES = PLUGIN_ID + ".translation.taskPriorities"; //$NON-NLS-1$ + /** + * Possible configurable option value for TRANSLATION_TASK_PRIORITIES. + * @see #getDefaultOptions + */ + public static final String TRANSLATION_TASK_PRIORITY_HIGH = "HIGH"; //$NON-NLS-1$ + /** + * Possible configurable option value for TRANSLATION_TASK_PRIORITIES. + * @see #getDefaultOptions + */ + public static final String TRANSLATION_TASK_PRIORITY_LOW = "LOW"; //$NON-NLS-1$ + /** + * Possible configurable option value for TRANSLATION_TASK_PRIORITIES. + * @see #getDefaultOptions + */ + public static final String TRANSLATION_TASK_PRIORITY_NORMAL = "NORMAL"; //$NON-NLS-1$ + /** + * Possible configurable option ID. + * @see #getDefaultOptions + */ + public static final String TRANSLATION_TASK_TAGS = PLUGIN_ID + ".translation.taskTags"; //$NON-NLS-1$ + + /** + * Default task tag + */ + public static final String DEFAULT_TASK_TAG = "TODO"; //$NON-NLS-1$ + /** + * Default task priority + */ + public static final String DEFAULT_TASK_PRIORITY = TRANSLATION_TASK_PRIORITY_NORMAL; + /** + * Possible configurable option ID. + * @see #getDefaultOptions + */ + public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$ + private static CCorePlugin fgCPlugin; private static ResourceBundle fgResourceBundle; @@ -149,6 +195,202 @@ public class CCorePlugin extends Plugin { // Set the default for using the new parser getPluginPreferences().setDefault(PREF_USE_NEW_PARSER, true); } + + + /** + * TODO: Add all options here + * Returns a table of all known configurable options with their default values. + * These options allow to configure the behaviour of the underlying components. + * The client may safely use the result as a template that they can modify and + * then pass to setOptions. + * + * Helper constants have been defined on CCorePlugin for each of the option ID and + * their possible constant values. + * + * Note: more options might be added in further releases. + *
    +     * RECOGNIZED OPTIONS:
    +     * TRANSLATION / Define the Automatic Task Tags
    +     *    When the tag list is not empty, translation will issue a task marker whenever it encounters
    +     *    one of the corresponding tags inside any comment in C/C++ source code.
    +     *    Generated task messages will include the tag, and range until the next line separator or comment ending.
    +     *    Note that tasks messages are trimmed. If a tag is starting with a letter or digit, then it cannot be leaded by
    +     *    another letter or digit to be recognized ("fooToDo" will not be recognized as a task for tag "ToDo", but "foo#ToDo"
    +     *    will be detected for either tag "ToDo" or "#ToDo"). Respectively, a tag ending with a letter or digit cannot be followed
    +     *    by a letter or digit to be recognized ("ToDofoo" will not be recognized as a task for tag "ToDo", but "ToDo:foo" will
    +     *    be detected either for tag "ToDo" or "ToDo:").
    +     *     - option id:         "org.eclipse.cdt.core.translation.taskTags"
    +     *     - possible values:   { "[,]*" } where  is a String without any wild-card or leading/trailing spaces 
    +     *     - default:           ""
    +     * 
    +     * TRANSLATION / Define the Automatic Task Priorities
    +     *    In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
    +     *    of the task markers issued by the translation.
    +     *    If the default is specified, the priority of each task marker is "NORMAL".
    +     *     - option id:         "org.eclipse.cdt.core.transltaion.taskPriorities"
    +     *     - possible values:   { "[,]*" } where  is one of "HIGH", "NORMAL" or "LOW"
    +     *     - default:           ""
    +     * 
    +     * CORE / Specify Default Source Encoding Format
    +     *    Get the encoding format for translated sources. This setting is read-only, it is equivalent
    +     *    to 'ResourcesPlugin.getEncoding()'.
    +     *     - option id:         "org.eclipse.cdt.core.encoding"
    +     *     - possible values:   { any of the supported encoding names}.
    +     *     - default:           
    +     * 
    + * + * @return a mutable map containing the default settings of all known options + * (key type: String; value type: String) + * @see #setOptions + */ + + public static HashMap getDefaultOptions() + { + HashMap defaultOptions = new HashMap(10); + + // see #initializeDefaultPluginPreferences() for changing default settings + Preferences preferences = getDefault().getPluginPreferences(); + HashSet optionNames = CModelManager.OptionNames; + + // get preferences set to their default + String[] defaultPropertyNames = preferences.defaultPropertyNames(); + for (int i = 0; i < defaultPropertyNames.length; i++){ + String propertyName = defaultPropertyNames[i]; + if (optionNames.contains(propertyName)) { + defaultOptions.put(propertyName, preferences.getDefaultString(propertyName)); + } + } + // get preferences not set to their default + String[] propertyNames = preferences.propertyNames(); + for (int i = 0; i < propertyNames.length; i++){ + String propertyName = propertyNames[i]; + if (optionNames.contains(propertyName)) { + defaultOptions.put(propertyName, preferences.getDefaultString(propertyName)); + } + } + // get encoding through resource plugin + defaultOptions.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); + + return defaultOptions; + } + + + /** + * Initializes the default preferences settings for this plug-in. + * TODO: Add all options here + */ + protected void initializeDefaultPluginPreferences() + { + Preferences preferences = getPluginPreferences(); + HashSet optionNames = CModelManager.OptionNames; + + // Compiler settings + preferences.setDefault(TRANSLATION_TASK_TAGS, DEFAULT_TASK_TAG); + optionNames.add(TRANSLATION_TASK_TAGS); + + preferences.setDefault(TRANSLATION_TASK_PRIORITIES, DEFAULT_TASK_PRIORITY); + optionNames.add(TRANSLATION_TASK_PRIORITIES); + } + + /** + * Helper method for returning one option value only. Equivalent to (String)CCorePlugin.getOptions().get(optionName) + * Note that it may answer null if this option does not exist. + *

    + * For a complete description of the configurable options, see getDefaultOptions. + *

    + * + * @param optionName the name of an option + * @return the String value of a given option + * @see CCorePlugin#getDefaultOptions + */ + public static String getOption(String optionName) { + + if (CORE_ENCODING.equals(optionName)){ + return ResourcesPlugin.getEncoding(); + } + if (CModelManager.OptionNames.contains(optionName)){ + Preferences preferences = getDefault().getPluginPreferences(); + return preferences.getString(optionName).trim(); + } + return null; + } + + /** + * Returns the table of the current options. Initially, all options have their default values, + * and this method returns a table that includes all known options. + *

    + * For a complete description of the configurable options, see getDefaultOptions. + *

    + * + * @return table of current settings of all options + * (key type: String; value type: String) + * @see CCorePlugin#getDefaultOptions + */ + public static HashMap getOptions() { + + HashMap options = new HashMap(10); + + // see #initializeDefaultPluginPreferences() for changing default settings + Plugin plugin = getDefault(); + if (plugin != null) { + Preferences preferences = plugin.getPluginPreferences(); + HashSet optionNames = CModelManager.OptionNames; + + // get preferences set to their default + String[] defaultPropertyNames = preferences.defaultPropertyNames(); + for (int i = 0; i < defaultPropertyNames.length; i++){ + String propertyName = defaultPropertyNames[i]; + if (optionNames.contains(propertyName)){ + options.put(propertyName, preferences.getDefaultString(propertyName)); + } + } + // get preferences not set to their default + String[] propertyNames = preferences.propertyNames(); + for (int i = 0; i < propertyNames.length; i++){ + String propertyName = propertyNames[i]; + if (optionNames.contains(propertyName)){ + options.put(propertyName, preferences.getString(propertyName).trim()); + } + } + // get encoding through resource plugin + options.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); + } + return options; + } + + /** + * Sets the current table of options. All and only the options explicitly included in the given table + * are remembered; all previous option settings are forgotten, including ones not explicitly + * mentioned. + *

    + * For a complete description of the configurable options, see getDefaultOptions. + *

    + * + * @param newOptions the new options (key type: String; value type: String), + * or null to reset all options to their default values + * @see CCorePlugin#getDefaultOptions + */ + public static void setOptions(HashMap newOptions) { + + // see #initializeDefaultPluginPreferences() for changing default settings + Preferences preferences = getDefault().getPluginPreferences(); + + if (newOptions == null){ + newOptions = getDefaultOptions(); + } + Iterator keys = newOptions.keySet().iterator(); + while (keys.hasNext()){ + String key = (String)keys.next(); + if (!CModelManager.OptionNames.contains(key)) continue; // unrecognized option + if (key.equals(CORE_ENCODING)) continue; // skipped, contributed by resource prefs + String value = (String)newOptions.get(key); + preferences.setValue(key, value); + } + + // persist options + getDefault().savePluginPreferences(); + } + public IConsole getConsole(String id) { try { diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 2a2ac8dfaed..26f0a650eaf 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -7,6 +7,9 @@ * src/org/eclipse/cdt/internal/ui/preferences/CProjectPropertyPage.java * src/org/eclipse/cdt/internal/ui/CPluginResources.properties +2003-06-26 Victor Mozgin + Task tags support in C/C++ comments (initial revision). + 2003-06-25 John Camelon Create new interface and support for calculating lineNumber/offset mapping. Updated IASTClassSpecifier for qualified name query. diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index 3ebf6f408fb..d863eaaca54 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -75,6 +75,9 @@ CApplicationLauncher.label=Executable CApplicationLauncher.description=Launch a local command CProblemMarker.name=C Problem +todoPageName=C/C++ Task Tags +todoTaskPrefName=Task Tags + Editors.DefaultTextEditor = Default Text Editor AsmEditor.name = Assembly Editor diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index f9055aa7a2d..600d322a47b 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -316,6 +316,12 @@ class="org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage" id="org.eclipse.cdt.ui.preferneces.CBuildConsolePreferernces"> + + @@ -340,6 +346,13 @@ value="org.eclipse.cdt.core.managedBuildNature"> + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java index a84426e82ed..4d87a9576cc 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java @@ -37,6 +37,10 @@ public interface ICHelpContextIds { public static final String PROJECT_PROPERTY_PAGE= PREFIX + "new_project_property_page_context"; public static final String PROJ_CONF_BLOCK= PREFIX + "new_proj_conf_block_context"; + + public static final String TODO_TASK_INPUT_DIALOG= PREFIX + "todo_task_input_dialog_context"; //$NON-NLS-1$ + public static final String TODO_TASK_PROPERTY_PAGE= PREFIX + "tasktags_property_page_context"; //$NON-NLS-1$ + public static final String TODO_TASK_PREFERENCE_PAGE= PREFIX + "tasktags_preference_page_context"; //$NON-NLS-1$ // Console view public static final String CLEAR_CONSOLE_ACTION= PREFIX + "clear_console_action_context"; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index cfedda90b8c..cd7bf5e92fe 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -10,6 +10,7 @@ import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; @@ -27,6 +28,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; @@ -83,6 +85,8 @@ import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.tasklist.TaskList; + + /** * C specific text editor. */ @@ -94,6 +98,9 @@ public class CEditor extends TextEditor implements ISelectionChangedListener { private SearchForReferencesAction fSearchForReferencesAction; protected ISelectionChangedListener fStatusLineClearer; + + /** The property change listener */ + private PropertyChangeListener fPropertyChangeListener = new PropertyChangeListener(); protected final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' }; @@ -116,6 +123,21 @@ public class CEditor extends TextEditor implements ISelectionChangedListener { /** Preference key for linked position color */ public final static String LINKED_POSITION_COLOR = "linkedPositionColor"; //$NON-NLS-1$ + /** Preference key for compiler task tags */ + private final static String TRANSLATION_TASK_TAGS= CCorePlugin.TRANSLATION_TASK_TAGS; + + private class PropertyChangeListener implements org.eclipse.core.runtime.Preferences.IPropertyChangeListener, org.eclipse.jface.util.IPropertyChangeListener { + /* + * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + */ + public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent event) { + handlePreferencePropertyChanged(event); + } + public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) { + handlePreferencePropertyChanged(new org.eclipse.jface.util.PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())); + } + }; + /** * Default constructor. */ @@ -132,7 +154,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener { setRulerContextMenuId("#CEditorRulerContext"); //$NON-NLS-1$ setOutlinerContextMenuId("#CEditorOutlinerContext"); //$NON-NLS-1$ - fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this); + fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this); } /** @@ -361,6 +383,12 @@ public class CEditor extends TextEditor implements ISelectionChangedListener { fBracketMatcher.dispose(); fBracketMatcher = null; } + if (fPropertyChangeListener != null) { + Preferences preferences = CCorePlugin.getDefault().getPluginPreferences(); + preferences.removePropertyChangeListener(fPropertyChangeListener); + IPreferenceStore preferenceStore = getPreferenceStore(); + preferenceStore.removePropertyChangeListener(fPropertyChangeListener); + } super.dispose(); } @@ -460,6 +488,12 @@ public class CEditor extends TextEditor implements ISelectionChangedListener { if (isTabConversionEnabled()) startTabConversion(); + + IPreferenceStore preferenceStore = getPreferenceStore(); + preferenceStore.addPropertyChangeListener(fPropertyChangeListener); + + Preferences preferences = CCorePlugin.getDefault().getPluginPreferences(); + preferences.addPropertyChangeListener(fPropertyChangeListener); } private IMarker getNextError(int offset, boolean forward) { @@ -802,4 +836,18 @@ public class CEditor extends TextEditor implements ISelectionChangedListener { setKeyBindingScopes(new String [] { "org.eclipse.cdt.ui.cEditorScope" } ); } + /** + * Handles a property change event describing a change + * of the C core's preferences and updates the preference + * related editor properties. + * + * @param event the property change event + */ + protected void handlePreferencePropertyChanged(org.eclipse.jface.util.PropertyChangeEvent event) { + if (TRANSLATION_TASK_TAGS.equals(event.getProperty())) { + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer != null && affectsTextPresentation(event)) + sourceViewer.invalidateTextPresentation(); + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java index 16dc783e589..1cf2df4f909 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java @@ -177,8 +177,10 @@ public class CMarkerAnnotation extends MarkerAnnotation implements IProblemAnnot } else { if(marker.isSubtypeOf(ICModelMarker.C_MODEL_PROBLEM_MARKER)) { //|| getMarker().isSubtypeOf(IMarker.SEVERITY_WARNING)) { fIsProblemMarker= true; - } - fIsProblemMarker = true; + } else if (marker.isSubtypeOf(IMarker.TASK) || marker.isSubtypeOf(ICModelMarker.TASK_MARKER)) { + fIsProblemMarker= false; + } else + fIsProblemMarker = true; } } catch (CoreException e) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java index c229be4e23a..4f020ccfa07 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java @@ -6,9 +6,11 @@ package org.eclipse.cdt.internal.ui.editor.asm; */ import org.eclipse.cdt.internal.ui.text.ICColorConstants; +import org.eclipse.cdt.internal.ui.text.CCommentScanner; import org.eclipse.cdt.internal.ui.text.SingleTokenCScanner; import org.eclipse.cdt.internal.ui.text.util.CColorManager; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocumentPartitioner; import org.eclipse.jface.text.rules.DefaultPartitioner; @@ -24,11 +26,15 @@ import org.eclipse.jface.util.PropertyChangeEvent; */ public class AsmTextTools { - private class PreferenceListener implements IPropertyChangeListener { - public void propertyChange(PropertyChangeEvent event) { - adaptToPreferenceChange(event); - } - }; + private class PreferenceListener implements IPropertyChangeListener, Preferences.IPropertyChangeListener { + public void propertyChange(PropertyChangeEvent event) { + adaptToPreferenceChange(event); + } + public void propertyChange(Preferences.PropertyChangeEvent event) { + adaptToPreferenceChange(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())); + } + }; + /** The color manager -- use the same as for C code */ private CColorManager fColorManager; /** The Asm source code scanner */ @@ -36,15 +42,17 @@ public class AsmTextTools { /** The Asm partitions scanner */ private AsmPartitionScanner fPartitionScanner; /** The ASM multiline comment scanner */ - private SingleTokenCScanner fMultilineCommentScanner; + private CCommentScanner fMultilineCommentScanner; /** The ASM singleline comment scanner */ - private SingleTokenCScanner fSinglelineCommentScanner; + private CCommentScanner fSinglelineCommentScanner; /** The ASM string scanner */ private SingleTokenCScanner fStringScanner; /** The preference store */ - private IPreferenceStore fPreferenceStore; + private IPreferenceStore fPreferenceStore; + /** The core preference store */ + private Preferences fCorePreferenceStore; /** The preference change listener */ private PreferenceListener fPreferenceListener= new PreferenceListener(); @@ -54,17 +62,32 @@ public class AsmTextTools { * and initializes all members of this collection. */ public AsmTextTools(IPreferenceStore store) { + this(store, null); + } + + /** + * Creates a new Asm text tools collection and eagerly creates + * and initializes all members of this collection. + */ + public AsmTextTools(IPreferenceStore store, Preferences coreStore) { if(store == null) { store = CUIPlugin.getDefault().getPreferenceStore(); } + + fPreferenceStore = store; store.addPropertyChangeListener(fPreferenceListener); - fPreferenceStore = store; + + fCorePreferenceStore= coreStore; + if (fCorePreferenceStore != null) { + fCorePreferenceStore.addPropertyChangeListener(fPreferenceListener); + } + fColorManager= new CColorManager(); fCodeScanner= new AsmCodeScanner(fColorManager, store); fPartitionScanner= new AsmPartitionScanner(); - fMultilineCommentScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_MULTI_LINE_COMMENT); - fSinglelineCommentScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_SINGLE_LINE_COMMENT); + fMultilineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_MULTI_LINE_COMMENT); + fSinglelineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_SINGLE_LINE_COMMENT); fStringScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_STRING); } @@ -95,6 +118,12 @@ public class AsmTextTools { if (fPreferenceStore != null) { fPreferenceStore.removePropertyChangeListener(fPreferenceListener); fPreferenceStore= null; + + if (fCorePreferenceStore != null) { + fCorePreferenceStore.removePropertyChangeListener(fPreferenceListener); + fCorePreferenceStore= null; + } + fPreferenceListener= null; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java index e32130aa1e4..d9ebdfd129e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java @@ -22,6 +22,7 @@ import org.eclipse.cdt.internal.ui.text.CTextTools; import org.eclipse.cdt.internal.ui.text.ContentAssistPreference; import org.eclipse.cdt.internal.ui.text.ICColorConstants; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.preference.IPreferenceStore; @@ -71,7 +72,8 @@ public class CEditorPreferencePage extends PreferencePage implements IWorkbenchP "Keywords", ICColorConstants.C_KEYWORD }, { "Built-in types", ICColorConstants.C_TYPE }, { "Strings", ICColorConstants.C_STRING }, { - "Others", ICColorConstants.C_DEFAULT } + "Others", ICColorConstants.C_DEFAULT }, { + PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags"), PreferenceConstants.EDITOR_TASK_TAG_COLOR } }; protected final String[][] fAppearanceColorListModel = new String[][] { { "Line number color", TextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR }, //$NON-NLS-1$ @@ -245,6 +247,14 @@ public class CEditorPreferencePage extends PreferencePage implements IWorkbenchP //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PARAMETERS_BACKGROUND), //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PARAMETERS_FOREGROUND), //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_JAVADOC), + + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_TASK_TAG_COLOR)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_TASK_TAG_BOLD)); + + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_TASK_INDICATION_COLOR)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_TASK_INDICATION)); + + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER)); OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()]; overlayKeys.toArray(keys); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java new file mode 100644 index 00000000000..7e60038515c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; + +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.CCorePlugin; + +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; +import org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener; + +/** + */ +public abstract class OptionsConfigurationBlock { + + protected static class ControlData { + private String fKey; + private String[] fValues; + + public ControlData(String key, String[] values) { + fKey= key; + fValues= values; + } + + public String getKey() { + return fKey; + } + + public String getValue(boolean selection) { + int index= selection ? 0 : 1; + return fValues[index]; + } + + public String getValue(int index) { + return fValues[index]; + } + + public int getSelection(String value) { + for (int i= 0; i < fValues.length; i++) { + if (value.equals(fValues[i])) { + return i; + } + } + throw new IllegalArgumentException(); + } + } + + + protected Map fWorkingValues; + + protected ArrayList fCheckBoxes; + protected ArrayList fComboBoxes; + protected ArrayList fTextBoxes; + + private SelectionListener fSelectionListener; + private ModifyListener fTextModifyListener; + + protected IStatusChangeListener fContext; + protected ICProject fProject; // project or null + + private Shell fShell; + + public OptionsConfigurationBlock(IStatusChangeListener context, ICProject project) { + fContext= context; + fProject= project; + + fWorkingValues= getOptions(true); + + fCheckBoxes= new ArrayList(); + fComboBoxes= new ArrayList(); + fTextBoxes= new ArrayList(2); + } + + protected abstract String[] getAllKeys(); + + protected Map getOptions(boolean inheritCCoreOptions) { + if (fProject != null) { + return fProject.getOptions(inheritCCoreOptions); + } else { + return CCorePlugin.getOptions(); + } + } + + protected Map getDefaultOptions() { + return CCorePlugin.getDefaultOptions(); + } + + public final boolean hasProjectSpecificOptions() { + if (fProject != null) { + Map settings= fProject.getOptions(false); + String[] allKeys= getAllKeys(); + for (int i= 0; i < allKeys.length; i++) { + if (settings.get(allKeys[i]) != null) { + return true; + } + } + } + return false; + } + + protected final void setOptions(Map map) { + if (fProject != null) { + fProject.setOptions(map); + } else { + CCorePlugin.setOptions((HashMap) map); + } + } + + protected Shell getShell() { + return fShell; + } + + protected void setShell(Shell shell) { + fShell= shell; + } + + protected abstract Control createContents(Composite parent); + + protected void addCheckBox(Composite parent, String label, String key, String[] values, int indent) { + ControlData data= new ControlData(key, values); + + GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan= 2; + gd.horizontalIndent= indent; + + Button checkBox= new Button(parent, SWT.CHECK); + checkBox.setText(label); + checkBox.setData(data); + checkBox.setLayoutData(gd); + checkBox.addSelectionListener(getSelectionListener()); + + String currValue= (String)fWorkingValues.get(key); + checkBox.setSelection(data.getSelection(currValue) == 0); + + fCheckBoxes.add(checkBox); + } + + protected void addComboBox(Composite parent, String label, String key, String[] values, String[] valueLabels, int indent) { + ControlData data= new ControlData(key, values); + + GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalIndent= indent; + + Label labelControl= new Label(parent, SWT.LEFT | SWT.WRAP); + labelControl.setText(label); + labelControl.setLayoutData(gd); + + Combo comboBox= new Combo(parent, SWT.READ_ONLY); + comboBox.setItems(valueLabels); + comboBox.setData(data); + comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + comboBox.addSelectionListener(getSelectionListener()); + + String currValue= (String)fWorkingValues.get(key); + comboBox.select(data.getSelection(currValue)); + + fComboBoxes.add(comboBox); + } + + protected Text addTextField(Composite parent, String label, String key, int indent, int widthHint) { + Label labelControl= new Label(parent, SWT.NONE); + labelControl.setText(label); + labelControl.setLayoutData(new GridData()); + + Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE); + textBox.setData(key); + textBox.setLayoutData(new GridData()); + + String currValue= (String) fWorkingValues.get(key); + textBox.setText(currValue); + textBox.addModifyListener(getTextModifyListener()); + + GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL); + if (widthHint != 0) { + data.widthHint= widthHint; + } + data.horizontalIndent= indent; + textBox.setLayoutData(data); + + fTextBoxes.add(textBox); + return textBox; + } + + protected SelectionListener getSelectionListener() { + if (fSelectionListener == null) { + fSelectionListener= new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + controlChanged(e.widget); + } + }; + } + return fSelectionListener; + } + + protected ModifyListener getTextModifyListener() { + if (fTextModifyListener == null) { + fTextModifyListener= new ModifyListener() { + public void modifyText(ModifyEvent e) { + textChanged((Text) e.widget); + } + }; + } + return fTextModifyListener; + } + + protected void controlChanged(Widget widget) { + ControlData data= (ControlData) widget.getData(); + String newValue= null; + if (widget instanceof Button) { + newValue= data.getValue(((Button)widget).getSelection()); + } else if (widget instanceof Combo) { + newValue= data.getValue(((Combo)widget).getSelectionIndex()); + } else { + return; + } + fWorkingValues.put(data.getKey(), newValue); + + validateSettings(data.getKey(), newValue); + } + + protected void textChanged(Text textControl) { + String key= (String) textControl.getData(); + String number= textControl.getText(); + fWorkingValues.put(key, number); + validateSettings(key, number); + } + + protected boolean checkValue(String key, String value) { + return value.equals(fWorkingValues.get(key)); + } + + /* (non-javadoc) + * Update fields and validate. + * @param changedKey Key that changed, or null, if all changed. + */ + protected abstract void validateSettings(String changedKey, String newValue); + + + protected String[] getTokens(String text, String separator) { + StringTokenizer tok= new StringTokenizer(text, separator); //$NON-NLS-1$ + int nTokens= tok.countTokens(); + String[] res= new String[nTokens]; + for (int i= 0; i < res.length; i++) { + res[i]= tok.nextToken().trim(); + } + return res; + } + + + public boolean performOk(boolean enabled) { + String[] allKeys= getAllKeys(); + Map actualOptions= getOptions(false); + + // preserve other options + boolean hasChanges= false; + for (int i= 0; i < allKeys.length; i++) { + String key= allKeys[i]; + String oldVal= (String) actualOptions.get(key); + String val= null; + if (enabled) { + val= (String) fWorkingValues.get(key); + if (!val.equals(oldVal)) { + hasChanges= true; + actualOptions.put(key, val); + } + } else { + if (oldVal != null) { + actualOptions.remove(key); + hasChanges= true; + } + } + } + + + if (hasChanges) { + boolean doBuild= false; + String[] strings= getFullBuildDialogStrings(fProject == null); + if (strings != null) { + MessageDialog dialog= new MessageDialog(getShell(), strings[0], null, strings[1], MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 2); + int res= dialog.open(); + if (res == 0) { + doBuild= true; + } else if (res != 1) { + return false; // cancel pressed + } + } + setOptions(actualOptions); + if (doBuild) { + doFullBuild(); + } + } + return true; + } + + protected abstract String[] getFullBuildDialogStrings(boolean workspaceSettings); + + protected void doFullBuild() { + ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell()); + try { + dialog.run(true, true, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException { + monitor.beginTask("", 1); //$NON-NLS-1$ + try { + if (fProject != null) { + monitor.setTaskName(PreferencesMessages.getFormattedString("OptionsConfigurationBlock.buildproject.taskname", fProject.getElementName())); //$NON-NLS-1$ + fProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, new SubProgressMonitor(monitor,1)); + } else { + monitor.setTaskName(PreferencesMessages.getString("OptionsConfigurationBlock.buildall.taskname")); //$NON-NLS-1$ + CUIPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new SubProgressMonitor(monitor,1)); + } + } catch (CoreException e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); + } + } + }); + } catch (InterruptedException e) { + // cancelled by user + } catch (InvocationTargetException e) { + String title= PreferencesMessages.getString("OptionsConfigurationBlock.builderror.title"); //$NON-NLS-1$ + String message= PreferencesMessages.getString("OptionsConfigurationBlock.builderror.message"); //$NON-NLS-1$ + ExceptionHandler.handle(e, getShell(), title, message); + } + } + + public void performDefaults() { + fWorkingValues= getDefaultOptions(); + updateControls(); + validateSettings(null, null); + } + + protected void updateControls() { + // update the UI + for (int i= fCheckBoxes.size() - 1; i >= 0; i--) { + Button curr= (Button) fCheckBoxes.get(i); + ControlData data= (ControlData) curr.getData(); + + String currValue= (String) fWorkingValues.get(data.getKey()); + curr.setSelection(data.getSelection(currValue) == 0); + } + for (int i= fComboBoxes.size() - 1; i >= 0; i--) { + Combo curr= (Combo) fComboBoxes.get(i); + ControlData data= (ControlData) curr.getData(); + + String currValue= (String) fWorkingValues.get(data.getKey()); + curr.select(data.getSelection(currValue)); + } + for (int i= fTextBoxes.size() - 1; i >= 0; i--) { + Text curr= (Text) fTextBoxes.get(i); + String key= (String) curr.getData(); + + String currValue= (String) fWorkingValues.get(key); + curr.setText(currValue); + } + } + + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java new file mode 100644 index 00000000000..5910c5af1c6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class PreferencesMessages { + + private static final String RESOURCE_BUNDLE= "org.eclipse.cdt.internal.ui.preferences.PreferencesMessages";//$NON-NLS-1$ + + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private PreferencesMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + public static String getFormattedString(String key, String arg) { + return getFormattedString(key, new String[] { arg }); + } + + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getString(key), args); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties new file mode 100644 index 00000000000..d3be009d62e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -0,0 +1,51 @@ +############################################################################### +# Copyright (c) 2000, 2003 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Common Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/cpl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### + +OptionsConfigurationBlock.builderror.title=Preference Changes +OptionsConfigurationBlock.builderror.message=Problem while building. Check log for details. + +OptionsConfigurationBlock.buildall.taskname=Build all... +OptionsConfigurationBlock.buildproject.taskname=Build project ''{0}''... + + +TodoTaskPreferencePage.title=Task Tags + +TodoTaskPropertyPage.useworkspacesettings.label=Use &workspace settings +TodoTaskPropertyPage.useworkspacesettings.change=&Configure Workspace Settings... +TodoTaskPropertyPage.useprojectsettings.label=Use pr&oject settings + +TodoTaskConfigurationBlock.markers.tasks.high.priority=High +TodoTaskConfigurationBlock.markers.tasks.normal.priority=Normal +TodoTaskConfigurationBlock.markers.tasks.low.priority=Low +TodoTaskConfigurationBlock.markers.tasks.label=&Strings indicating tasks in Java comments: +TodoTaskConfigurationBlock.markers.tasks.add.button=Ne&w... +TodoTaskConfigurationBlock.markers.tasks.remove.button=Remo&ve +TodoTaskConfigurationBlock.markers.tasks.edit.button=Edi&t... +TodoTaskConfigurationBlock.markers.tasks.name.column=Tag +TodoTaskConfigurationBlock.markers.tasks.priority.column=Priority + +TodoTaskConfigurationBlock.needsbuild.title=Task Tags Settings Changed +TodoTaskConfigurationBlock.needsfullbuild.message=The task tags settings have changed. A full rebuild is required to make changes effective. Do the full build now? +TodoTaskConfigurationBlock.needsprojectbuild.message=The task tags settings have changed. A rebuild of the project is required to make changes effective. Do the project build now? + +TodoTaskInputDialog.new.title=New Task Tag +TodoTaskInputDialog.edit.title=Edit Task Tag +TodoTaskInputDialog.name.label=T&ag: +TodoTaskInputDialog.priority.label=&Priority: +TodoTaskInputDialog.priority.high=High +TodoTaskInputDialog.priority.normal=Normal +TodoTaskInputDialog.priority.low=Low +TodoTaskInputDialog.error.enterName=Enter task tag name. +TodoTaskInputDialog.error.comma=Name cannot contain a comma. +TodoTaskInputDialog.error.entryExists=Entry with the same name already exists. +TodoTaskInputDialog.error.noSpace=Name can not start or end with a whitespace. + +CEditorPreferencePage.cCommentTaskTags=Task Tags diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskConfigurationBlock.java new file mode 100644 index 00000000000..acb827d360f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskConfigurationBlock.java @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Table; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.ICProject; + +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.util.PixelConverter; +import org.eclipse.cdt.internal.ui.util.SWTUtil; +import org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IListAdapter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField; + +/** + */ +public class TodoTaskConfigurationBlock extends OptionsConfigurationBlock { + + private static final String PREF_TRANSLATION_TASK_TAGS= CCorePlugin.TRANSLATION_TASK_TAGS; + private static final String PREF_TRANSLATION_TASK_PRIORITIES= CCorePlugin.TRANSLATION_TASK_PRIORITIES; + + private static final String PRIORITY_HIGH= CCorePlugin.TRANSLATION_TASK_PRIORITY_HIGH; + private static final String PRIORITY_NORMAL= CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL; + private static final String PRIORITY_LOW= CCorePlugin.TRANSLATION_TASK_PRIORITY_LOW; + + public static class TodoTask { + public String name; + public String priority; + } + + private static class TodoTaskLabelProvider extends LabelProvider implements ITableLabelProvider { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) + */ + public Image getImage(Object element) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + return getColumnText(element, 0); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) + */ + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) + */ + public String getColumnText(Object element, int columnIndex) { + TodoTask task= (TodoTask) element; + if (columnIndex == 0) { + return task.name; + } else { + if (PRIORITY_HIGH.equals(task.priority)) { + return PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.high.priority"); //$NON-NLS-1$ + } else if (PRIORITY_NORMAL.equals(task.priority)) { + return PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.normal.priority"); //$NON-NLS-1$ + } else if (PRIORITY_LOW.equals(task.priority)) { + return PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.low.priority"); //$NON-NLS-1$ + } + return ""; //$NON-NLS-1$ + } + } + + } + + private PixelConverter fPixelConverter; + + private IStatus fTaskTagsStatus; + private ListDialogField fTodoTasksList; + + public TodoTaskConfigurationBlock(IStatusChangeListener context, ICProject project) { + super(context, project); + + TaskTagAdapter adapter= new TaskTagAdapter(); + String[] buttons= new String[] { + /* 0 */ PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.add.button"), //$NON-NLS-1$ + /* 1 */ PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.remove.button"), //$NON-NLS-1$ + null, + /* 3 */ PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.edit.button"), //$NON-NLS-1$ + }; + fTodoTasksList= new ListDialogField(adapter, buttons, new TodoTaskLabelProvider()); + fTodoTasksList.setDialogFieldListener(adapter); + fTodoTasksList.setLabelText(PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.label")); //$NON-NLS-1$ + fTodoTasksList.setRemoveButtonIndex(1); + + String[] columnsHeaders= new String[] { + PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.name.column"), //$NON-NLS-1$ + PreferencesMessages.getString("TodoTaskConfigurationBlock.markers.tasks.priority.column"), //$NON-NLS-1$ + }; + + fTodoTasksList.setTableColumns(new ListDialogField.ColumnsDescription(columnsHeaders, true)); + unpackTodoTasks(); + if (fTodoTasksList.getSize() > 0) { + fTodoTasksList.selectFirstElement(); + } else { + fTodoTasksList.enableButton(3, false); + } + + fTaskTagsStatus= new StatusInfo(); + } + + protected final String[] getAllKeys() { + return new String[] { + PREF_TRANSLATION_TASK_TAGS, PREF_TRANSLATION_TASK_PRIORITIES + }; + } + + public class TaskTagAdapter implements IListAdapter, IDialogFieldListener { + + private boolean canEdit(ListDialogField field) { + return field.getSelectedElements().size() == 1; + } + + public void customButtonPressed(ListDialogField field, int index) { + doTodoButtonPressed(index); + } + + public void selectionChanged(ListDialogField field) { + field.enableButton(3, canEdit(field)); + } + + public void doubleClicked(ListDialogField field) { + if (canEdit(field)) { + doTodoButtonPressed(3); + } + } + + public void dialogFieldChanged(DialogField field) { + validateSettings(PREF_TRANSLATION_TASK_TAGS, null); + } + + } + + protected Control createContents(Composite parent) { + fPixelConverter= new PixelConverter(parent); + setShell(parent.getShell()); + + Composite markersComposite= createMarkersTabContent(parent); + + validateSettings(null, null); + + return markersComposite; + } + + private Composite createMarkersTabContent(Composite folder) { + + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 2; + + Composite markersComposite= new Composite(folder, SWT.NULL); + markersComposite.setLayout(layout); + + fTodoTasksList.doFillIntoGrid(markersComposite, 3); + LayoutUtil.setHorizontalSpan(fTodoTasksList.getLabelControl(null), 2); + + Table table= fTodoTasksList.getTableViewer().getTable(); + GridData data= (GridData)fTodoTasksList.getListControl(null).getLayoutData(); + data.grabExcessHorizontalSpace= true; + data.verticalAlignment= 0; + data.heightHint= SWTUtil.getTableHeightHint(table, 6); + + return markersComposite; + } + + protected void validateSettings(String changedKey, String newValue) { + if (changedKey != null) { + if (PREF_TRANSLATION_TASK_TAGS.equals(changedKey)) { + fTaskTagsStatus= validateTaskTags(); + } else { + return; + } + } else { + fTaskTagsStatus= validateTaskTags(); + } + IStatus status= fTaskTagsStatus; //StatusUtil.getMostSevere(new IStatus[] { fTaskTagsStatus }); + fContext.statusChanged(status); + } + + private IStatus validateTaskTags() { + return new StatusInfo(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#performOk(boolean) + */ + public boolean performOk(boolean enabled) { + packTodoTasks(); + return super.performOk(enabled); + } + + + protected String[] getFullBuildDialogStrings(boolean workspaceSettings) { + String title= PreferencesMessages.getString("TodoTaskConfigurationBlock.needsbuild.title"); //$NON-NLS-1$ + String message; + if (fProject == null) { + message= PreferencesMessages.getString("TodoTaskConfigurationBlock.needsfullbuild.message"); //$NON-NLS-1$ + } else { + message= PreferencesMessages.getString("TodoTaskConfigurationBlock.needsprojectbuild.message"); //$NON-NLS-1$ + } + return new String[] { title, message }; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls() + */ + protected void updateControls() { + unpackTodoTasks(); + } + + private void unpackTodoTasks() { + String currTags= (String) fWorkingValues.get(PREF_TRANSLATION_TASK_TAGS); + String currPrios= (String) fWorkingValues.get(PREF_TRANSLATION_TASK_PRIORITIES); + String[] tags= getTokens(currTags, ","); //$NON-NLS-1$ + String[] prios= getTokens(currPrios, ","); //$NON-NLS-1$ + ArrayList elements= new ArrayList(tags.length); + for (int i= 0; i < tags.length; i++) { + TodoTask task= new TodoTask(); + task.name= tags[i].trim(); + task.priority= (i < prios.length) ? prios[i] : PRIORITY_NORMAL; + elements.add(task); + } + fTodoTasksList.setElements(elements); + } + + private void packTodoTasks() { + StringBuffer tags= new StringBuffer(); + StringBuffer prios= new StringBuffer(); + List list= fTodoTasksList.getElements(); + for (int i= 0; i < list.size(); i++) { + if (i > 0) { + tags.append(','); + prios.append(','); + } + TodoTask elem= (TodoTask) list.get(i); + tags.append(elem.name); + prios.append(elem.priority); + } + fWorkingValues.put(PREF_TRANSLATION_TASK_TAGS, tags.toString()); + fWorkingValues.put(PREF_TRANSLATION_TASK_PRIORITIES, prios.toString()); + } + + private void doTodoButtonPressed(int index) { + TodoTask edited= null; + if (index != 0) { + edited= (TodoTask) fTodoTasksList.getSelectedElements().get(0); + } + + TodoTaskInputDialog dialog= new TodoTaskInputDialog(getShell(), edited, fTodoTasksList.getElements()); + if (dialog.open() == TodoTaskInputDialog.OK) { + if (edited != null) { + fTodoTasksList.replaceElement(edited, dialog.getResult()); + } else { + fTodoTasksList.addElement(dialog.getResult()); + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskInputDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskInputDialog.java new file mode 100644 index 00000000000..ee630116f17 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskInputDialog.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.ui.help.WorkbenchHelp; + +import org.eclipse.cdt.core.CCorePlugin; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.dialogs.StatusDialog; +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.preferences.TodoTaskConfigurationBlock.TodoTask; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.ComboDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; + +/** + * Dialog to enter a na new task tag + */ +public class TodoTaskInputDialog extends StatusDialog { + + private class CompilerTodoTaskInputAdapter implements IDialogFieldListener { + public void dialogFieldChanged(DialogField field) { + doValidation(); + } + } + + private StringDialogField fNameDialogField; + private ComboDialogField fPriorityDialogField; + + private List fExistingNames; + + public TodoTaskInputDialog(Shell parent, TodoTask task, List existingEntries) { + super(parent); + + fExistingNames= new ArrayList(existingEntries.size()); + for (int i= 0; i < existingEntries.size(); i++) { + TodoTask curr= (TodoTask) existingEntries.get(i); + if (!curr.equals(task)) { + fExistingNames.add(curr.name); + } + } + + if (task == null) { + setTitle(PreferencesMessages.getString("TodoTaskInputDialog.new.title")); //$NON-NLS-1$ + } else { + setTitle(PreferencesMessages.getString("TodoTaskInputDialog.edit.title")); //$NON-NLS-1$ + } + + CompilerTodoTaskInputAdapter adapter= new CompilerTodoTaskInputAdapter(); + + fNameDialogField= new StringDialogField(); + fNameDialogField.setLabelText(PreferencesMessages.getString("TodoTaskInputDialog.name.label")); //$NON-NLS-1$ + fNameDialogField.setDialogFieldListener(adapter); + + fNameDialogField.setText((task != null) ? task.name : ""); //$NON-NLS-1$ + + String[] items= new String[] { + PreferencesMessages.getString("TodoTaskInputDialog.priority.high"), //$NON-NLS-1$ + PreferencesMessages.getString("TodoTaskInputDialog.priority.normal"), //$NON-NLS-1$ + PreferencesMessages.getString("TodoTaskInputDialog.priority.low") //$NON-NLS-1$ + }; + + fPriorityDialogField= new ComboDialogField(SWT.READ_ONLY); + fPriorityDialogField.setLabelText(PreferencesMessages.getString("TodoTaskInputDialog.priority.label")); //$NON-NLS-1$ + fPriorityDialogField.setItems(items); + if (task != null) { + if (CCorePlugin.TRANSLATION_TASK_PRIORITY_HIGH.equals(task.priority)) { + fPriorityDialogField.selectItem(0); + } else if (CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL.equals(task.priority)) { + fPriorityDialogField.selectItem(1); + } else { + fPriorityDialogField.selectItem(2); + } + } else { + fPriorityDialogField.selectItem(1); + } + } + + public TodoTask getResult() { + TodoTask task= new TodoTask(); + task.name= fNameDialogField.getText().trim(); + switch (fPriorityDialogField.getSelectionIndex()) { + case 0 : + task.priority= CCorePlugin.TRANSLATION_TASK_PRIORITY_HIGH; + break; + case 1 : + task.priority= CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL; + break; + default : + task.priority= CCorePlugin.TRANSLATION_TASK_PRIORITY_LOW; + break; + } + return task; + } + + protected Control createDialogArea(Composite parent) { + Composite composite= (Composite) super.createDialogArea(parent); + + Composite inner= new Composite(composite, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 2; + inner.setLayout(layout); + + fNameDialogField.doFillIntoGrid(inner, 2); + fPriorityDialogField.doFillIntoGrid(inner, 2); + + LayoutUtil.setHorizontalGrabbing(fNameDialogField.getTextControl(null)); + LayoutUtil.setWidthHint(fNameDialogField.getTextControl(null), convertWidthInCharsToPixels(45)); + + fNameDialogField.postSetFocusOnDialogField(parent.getDisplay()); + + applyDialogFont(composite); + return composite; + } + + private void doValidation() { + StatusInfo status= new StatusInfo(); + String newText= fNameDialogField.getText(); + if (newText.length() == 0) { + status.setError(PreferencesMessages.getString("TodoTaskInputDialog.error.enterName")); //$NON-NLS-1$ + } else { + if (newText.indexOf(',') != -1) { + status.setError(PreferencesMessages.getString("TodoTaskInputDialog.error.comma")); //$NON-NLS-1$ + } else if (fExistingNames.contains(newText)) { + status.setError(PreferencesMessages.getString("TodoTaskInputDialog.error.entryExists")); //$NON-NLS-1$ + } else if (Character.isWhitespace(newText.charAt(0)) || Character.isWhitespace(newText.charAt(newText.length() - 1))) { + status.setError(PreferencesMessages.getString("TodoTaskInputDialog.error.noSpace")); //$NON-NLS-1$ + } + } + updateStatus(status); + } + + /* + * @see org.eclipse.jface.window.Window#configureShell(Shell) + */ + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + WorkbenchHelp.setHelp(newShell, ICHelpContextIds.TODO_TASK_INPUT_DIALOG); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java new file mode 100644 index 00000000000..61a03d9d461 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPreferencePage.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.preference.PreferencePage; + +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.help.WorkbenchHelp; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.dialogs.StatusUtil; +import org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener; + +/* + * The page to configure the compiler options. + */ +public class TodoTaskPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IStatusChangeListener { + + public static final String ID= "org.eclipse.cdt.ui.propertyPages.TodoTaskPropertyPage"; //$NON-NLS-1$ + + private TodoTaskConfigurationBlock fConfigurationBlock; + + public TodoTaskPreferencePage() { + setPreferenceStore(CUIPlugin.getDefault().getPreferenceStore()); + //setDescription(PreferencesMessages.getString("TodoTaskPreferencePage.description")); //$NON-NLS-1$ + + // only used when page is shown programatically + setTitle(PreferencesMessages.getString("TodoTaskPreferencePage.title")); //$NON-NLS-1$ + + fConfigurationBlock= new TodoTaskConfigurationBlock(this, null); + } + + /* + * @see IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + + /* + * @see PreferencePage#createControl(Composite) + */ + public void createControl(Composite parent) { + // added for 1GEUGE6: ITPJUI:WIN2000 - Help is the same on all preference pages + super.createControl(parent); + WorkbenchHelp.setHelp(getControl(), ICHelpContextIds.TODO_TASK_PREFERENCE_PAGE); + } + + /* + * @see PreferencePage#createContents(Composite) + */ + protected Control createContents(Composite parent) { + Control result= fConfigurationBlock.createContents(parent); + Dialog.applyDialogFont(result); + return result; + } + + /* + * @see IPreferencePage#performOk() + */ + public boolean performOk() { + if (!fConfigurationBlock.performOk(true)) { + return false; + } + return super.performOk(); + } + + /* + * @see PreferencePage#performDefaults() + */ + protected void performDefaults() { + fConfigurationBlock.performDefaults(); + super.performDefaults(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus) + */ + public void statusChanged(IStatus status) { + setValid(!status.matches(IStatus.ERROR)); + StatusUtil.applyToStatusLine(this, status); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPropertyPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPropertyPage.java new file mode 100644 index 00000000000..f7a87a8fc2a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TodoTaskPropertyPage.java @@ -0,0 +1,219 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.jface.dialogs.ControlEnableState; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.preference.IPreferenceNode; +import org.eclipse.jface.preference.IPreferencePage; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.preference.PreferenceManager; +import org.eclipse.jface.preference.PreferenceNode; + +import org.eclipse.ui.dialogs.PropertyPage; +import org.eclipse.ui.help.WorkbenchHelp; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.dialogs.StatusUtil; +import org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; + +/** + * Property page used to configure project specific task tags settings + */ +public class TodoTaskPropertyPage extends PropertyPage { + + private TodoTaskConfigurationBlock fConfigurationBlock; + private Control fConfigurationBlockControl; + private ControlEnableState fBlockEnableState; + private SelectionButtonDialogField fUseWorkspaceSettings; + private SelectionButtonDialogField fChangeWorkspaceSettings; + private SelectionButtonDialogField fUseProjectSettings; + private IStatus fBlockStatus; + + + public TodoTaskPropertyPage() { + fBlockStatus= new StatusInfo(); + fBlockEnableState= null; + + IDialogFieldListener listener= new IDialogFieldListener() { + public void dialogFieldChanged(DialogField field) { + doDialogFieldChanged(field); + } + }; + + fUseWorkspaceSettings= new SelectionButtonDialogField(SWT.RADIO); + fUseWorkspaceSettings.setDialogFieldListener(listener); + fUseWorkspaceSettings.setLabelText(PreferencesMessages.getString("TodoTaskPropertyPage.useworkspacesettings.label")); //$NON-NLS-1$ + + fChangeWorkspaceSettings= new SelectionButtonDialogField(SWT.PUSH); + fChangeWorkspaceSettings.setLabelText(PreferencesMessages.getString("TodoTaskPropertyPage.useworkspacesettings.change")); //$NON-NLS-1$ + fChangeWorkspaceSettings.setDialogFieldListener(listener); + + fUseWorkspaceSettings.attachDialogField(fChangeWorkspaceSettings); + + fUseProjectSettings= new SelectionButtonDialogField(SWT.RADIO); + fUseProjectSettings.setDialogFieldListener(listener); + fUseProjectSettings.setLabelText(PreferencesMessages.getString("TodoTaskPropertyPage.useprojectsettings.label")); //$NON-NLS-1$ + } + + /* + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite parent) { + super.createControl(parent); + WorkbenchHelp.setHelp(getControl(), ICHelpContextIds.TODO_TASK_PROPERTY_PAGE); + } + + /* + * @see org.eclipse.jface.preference.IPreferencePage#createContents(Composite) + */ + protected Control createContents(Composite parent) { + IStatusChangeListener listener= new IStatusChangeListener() { + public void statusChanged(IStatus status) { + fBlockStatus= status; + doStatusChanged(); + } + }; + fConfigurationBlock= new TodoTaskConfigurationBlock(listener, getProject()); + + Composite composite= new Composite(parent, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 1; + composite.setLayout(layout); + + fUseWorkspaceSettings.doFillIntoGrid(composite, 1); + LayoutUtil.setHorizontalGrabbing(fUseWorkspaceSettings.getSelectionButton(null)); + + fChangeWorkspaceSettings.doFillIntoGrid(composite, 1); + GridData data= (GridData) fChangeWorkspaceSettings.getSelectionButton(null).getLayoutData(); + data.horizontalIndent= convertWidthInCharsToPixels(3); + data.horizontalAlignment= GridData.BEGINNING; + + fUseProjectSettings.doFillIntoGrid(composite, 1); + + data= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL ); + data.horizontalSpan= 1; + data.horizontalIndent= convertWidthInCharsToPixels(2); + + fConfigurationBlockControl= fConfigurationBlock.createContents(composite); + fConfigurationBlockControl.setLayoutData(data); + + boolean useProjectSettings= fConfigurationBlock.hasProjectSpecificOptions(); + + fUseProjectSettings.setSelection(useProjectSettings); + fUseWorkspaceSettings.setSelection(!useProjectSettings); + + updateEnableState(); + Dialog.applyDialogFont(composite); + return composite; + } + + private boolean useProjectSettings() { + return fUseProjectSettings.isSelected(); + } + + private void doDialogFieldChanged(DialogField field) { + if (field == fChangeWorkspaceSettings) { + TodoTaskPreferencePage page= new TodoTaskPreferencePage(); + showPreferencePage(TodoTaskPreferencePage.ID, page); + } else { + updateEnableState(); + doStatusChanged(); + } + } + /** + * Method statusChanged. + */ + private void doStatusChanged() { + updateStatus(useProjectSettings() ? fBlockStatus : new StatusInfo()); + } + + /** + * Method getProject. + */ + private ICProject getProject() { + return (ICProject) getElement().getAdapter(ICElement.class); + } + + private void updateEnableState() { + if (useProjectSettings()) { + if (fBlockEnableState != null) { + fBlockEnableState.restore(); + fBlockEnableState= null; + } + } else { + if (fBlockEnableState == null) { + fBlockEnableState= ControlEnableState.disable(fConfigurationBlockControl); + } + } + } + + /* + * @see org.eclipse.jface.preference.IPreferencePage#performDefaults() + */ + protected void performDefaults() { + if (useProjectSettings()) { + fUseProjectSettings.setSelection(false); + fUseWorkspaceSettings.setSelection(true); + fConfigurationBlock.performDefaults(); + } + super.performDefaults(); + } + + /* + * @see org.eclipse.jface.preference.IPreferencePage#performOk() + */ + public boolean performOk() { + return fConfigurationBlock.performOk(useProjectSettings()); + } + + private void updateStatus(IStatus status) { + setValid(!status.matches(IStatus.ERROR)); + StatusUtil.applyToStatusLine(this, status); + } + + private boolean showPreferencePage(String id, IPreferencePage page) { + final IPreferenceNode targetNode = new PreferenceNode(id, page); + + PreferenceManager manager = new PreferenceManager(); + manager.addToRoot(targetNode); + final PreferenceDialog dialog = new PreferenceDialog(getShell(), manager); + final boolean [] result = new boolean[] { false }; + BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { + public void run() { + dialog.create(); + dialog.setMessage(targetNode.getLabelText()); + result[0]= (dialog.open() == PreferenceDialog.OK); + } + }); + return result[0]; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java new file mode 100644 index 00000000000..e8c9f852c05 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text; + + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.Preferences; +import org.eclipse.cdt.core.CCorePlugin; + +import org.eclipse.cdt.internal.ui.text.IColorManager; +import org.eclipse.cdt.internal.ui.text.ICColorConstants; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * CCommentScanner.java + */ +public class CCommentScanner extends AbstractCScanner +{ + private static class TaskTagDetector implements IWordDetector { + + public boolean isWordStart(char c) { + return Character.isLetter(c); + } + + public boolean isWordPart(char c) { + return Character.isLetter(c); + } + }; + + private class TaskTagRule extends WordRule { + + private IToken fToken; + + public TaskTagRule(IToken token) { + super(new TaskTagDetector(), Token.UNDEFINED); + fToken= token; + } + + public void clearTaskTags() { + fWords.clear(); + } + + public void addTaskTags(String value) { + String[] tasks= split(value, ","); //$NON-NLS-1$ + for (int i= 0; i < tasks.length; i++) { + if (tasks[i].length() > 0) { + addWord(tasks[i], fToken); + } + } + } + + private String[] split(String value, String delimiters) { + StringTokenizer tokenizer= new StringTokenizer(value, delimiters); + int size= tokenizer.countTokens(); + String[] tokens= new String[size]; + int i= 0; + while (i < size) + tokens[i++]= tokenizer.nextToken(); + return tokens; + } + } + + private static final String TRANSLATION_TASK_TAGS= CCorePlugin.TRANSLATION_TASK_TAGS; + protected static final String TASK_TAG= ICColorConstants.TASK_TAG; + + private TaskTagRule fTaskTagRule; + private Preferences fCorePreferenceStore; + private String fDefaultTokenProperty; + private String[] fTokenProperties; + + public CCommentScanner(IColorManager manager, IPreferenceStore store, Preferences coreStore, String defaultTokenProperty) { + this(manager, store, coreStore, defaultTokenProperty, new String[] { defaultTokenProperty, TASK_TAG }); + } + + public CCommentScanner(IColorManager manager, IPreferenceStore store, Preferences coreStore, String defaultTokenProperty, String[] tokenProperties) { + super(manager, store); + + fCorePreferenceStore= coreStore; + fDefaultTokenProperty= defaultTokenProperty; + fTokenProperties= tokenProperties; + + initialize(); + } + + /* + * @see AbstractCScanner#createRules() + */ + protected List createRules() { + List list= new ArrayList(); + + if (fCorePreferenceStore != null) { + // Add rule for Task Tags. + fTaskTagRule= new TaskTagRule(getToken(TASK_TAG)); + String tasks= fCorePreferenceStore.getString(TRANSLATION_TASK_TAGS); + fTaskTagRule.addTaskTags(tasks); + list.add(fTaskTagRule); + } + + setDefaultReturnToken(getToken(fDefaultTokenProperty)); + + return list; + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractJavaScanner#affectsBehavior(org.eclipse.jface.util.PropertyChangeEvent) + */ + public boolean affectsBehavior(PropertyChangeEvent event) { + return event.getProperty().equals(TRANSLATION_TASK_TAGS) || super.affectsBehavior(event); + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractJavaScanner#adaptToPreferenceChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + public void adaptToPreferenceChange(PropertyChangeEvent event) { + if (fTaskTagRule != null && event.getProperty().equals(TRANSLATION_TASK_TAGS)) { + Object value= event.getNewValue(); + + if (value instanceof String) { + fTaskTagRule.clearTaskTags(); + fTaskTagRule.addTaskTags((String) value); + } + + } else if (super.affectsBehavior(event)) { + super.adaptToPreferenceChange(event); + } + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractJavaScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fTokenProperties; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CMultilineCommentScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CMultilineCommentScanner.java deleted file mode 100644 index 8ad9494df37..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CMultilineCommentScanner.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.eclipse.cdt.internal.ui.text; - -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ - - - -import org.eclipse.jface.text.rules.ICharacterScanner; -import org.eclipse.jface.text.rules.IRule; -import org.eclipse.jface.text.rules.IToken; -import org.eclipse.jface.text.rules.Token; -import org.eclipse.jface.util.Assert; - - -/** - * Implementation of IRule for C code scanning. - * Optimized to partition C documents - * Is is capable of detecting a pattern which begins with a given starting - * sequence and ends with a given ending sequence. If the ending sequence is - * not specified, it can be either end of line, end or file, or both. Additionally, - * the pattern can be constrained to begin in a certain column. - */ -public class CMultilineCommentScanner implements IRule { - - protected static final int UNDEFINED= -1; - - /** The token to be returned on success */ - protected IToken fToken; - - /** The pattern's escape character */ - protected char fEscapeCharacter; - /** Indicates whether end of line termines the pattern */ - protected boolean fBreaksOnEOL; - - /** - * Creates a rule for the given starting and ending sequence. - * When these sequences are detected the rule will return the specified token. - * Alternatively, the sequence can also be ended by the end of the line. - * Any character which follows the given escapeCharacter will be ignored. - * - * @param startSequence the pattern's start sequence - * @param endSequence the pattern's end sequence, null is a legal value - * @param token the token which will be returned on success - * @param escapeCharacter any character following this one will be ignored - * @param indicates whether the end of the line also termines the pattern - */ - public CMultilineCommentScanner(IToken token, char escapeCharacter, boolean breaksOnEOL) { - Assert.isNotNull(token); - - fToken= token; - fEscapeCharacter= escapeCharacter; - fBreaksOnEOL= breaksOnEOL; - } - - /** - * Returns whether the end sequence was detected. As the pattern can be considered - * ended by a line delimiter, the result of this method is true if the - * rule breaks on the end of the line, or if the EOF character is read. - * - * @param scanner the character scanner to be used - * @return true if the end sequence has been detected - */ - protected boolean endSequenceDetected(ICharacterScanner scanner) { - int c; - //char[][] delimiters= scanner.getLegalLineDelimiters(); - while ((c= scanner.read()) != ICharacterScanner.EOF) { - if (c == fEscapeCharacter) { - // Skip the escaped character. - scanner.read(); - } else if (c == '*') { - c = scanner.read(); - if(c == '/') { - return true; - } - scanner.unread(); - // Check if the specified end sequence has been found. - //} else if (fBreaksOnEOL) { - // Check for end of line since it can be used to terminate the pattern. - //for (int i= 0; i < delimiters.length; i++) { - // if (c == delimiters[i][0] && sequenceDetected(scanner, delimiters[i], false)) - // return true; - //} - } - } - scanner.unread(); - return true; - } - /* - * @see IRule#evaluate - */ - public IToken evaluate(ICharacterScanner scanner) { - - int c= scanner.read(); - - if (c == '/') { - if((c= scanner.read()) == '*') { - endSequenceDetected(scanner); - return fToken; - } - scanner.unread(); - } - - scanner.unread(); - return Token.UNDEFINED; - } - /** - * Returns whether the next characters to be read by the character scanner - * are an exact match with the given sequence. No escape characters are allowed - * within the sequence. If specified the sequence is considered to be found - * when reading the EOF character. - * - * @param scanner the character scanner to be used - * @param sequence the sequence to be detected - * @param eofAllowed indicated whether EOF terminates the pattern - * @return true if the given sequence has been detected - */ - protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) { - for (int i= 1; i < sequence.length; i++) { - int c= scanner.read(); - if (c == ICharacterScanner.EOF && eofAllowed) { - return true; - } else if (c != sequence[i]) { - // Non-matching character detected, rewind the scanner back to the start. - scanner.unread(); - for (int j= i-1; j > 0; j--) - scanner.unread(); - return false; - } - } - - return true; - } - /** - * Sets a column constraint for this rule. If set, the rule's token - * will only be returned if the pattern is detected starting at the - * specified column. If the column is smaller then 0, the column - * constraint is considered removed. - * - * @param column the column in which the pattern starts - */ - public void setColumnConstraint(int column) { - if (column < 0) - column= UNDEFINED; - //fColumn= column; - } -} - - diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java index dc566f237bd..2dc995fe0b5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java @@ -120,7 +120,6 @@ public class CPartitionScanner extends RuleBasedPartitionScanner { // Add rules for multi-line comments. rules.add(new MultiLineRule("/*", "*/", comment)); - //rules.add(new CMultilineCommentScanner(comment, (char)0, false)); IPredicateRule[] result= new IPredicateRule[rules.size()]; rules.toArray(result); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java index a4509c72122..e6fe8426818 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java @@ -8,6 +8,8 @@ package org.eclipse.cdt.internal.ui.text; import org.eclipse.cdt.internal.ui.text.util.CColorManager; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.runtime.Preferences; + import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocumentPartitioner; import org.eclipse.jface.text.rules.DefaultPartitioner; @@ -23,10 +25,13 @@ import org.eclipse.jface.util.PropertyChangeEvent; */ public class CTextTools { - private class PreferenceListener implements IPropertyChangeListener { + private class PreferenceListener implements IPropertyChangeListener, Preferences.IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { adaptToPreferenceChange(event); } + public void propertyChange(Preferences.PropertyChangeEvent event) { + adaptToPreferenceChange(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())); + } }; /** The color manager */ @@ -38,14 +43,16 @@ public class CTextTools { /** The C partitions scanner */ private FastCPartitionScanner fPartitionScanner; /** The Java multiline comment scanner */ - private SingleTokenCScanner fMultilineCommentScanner; + private CCommentScanner fMultilineCommentScanner; /** The Java singleline comment scanner */ - private SingleTokenCScanner fSinglelineCommentScanner; + private CCommentScanner fSinglelineCommentScanner; /** The Java string scanner */ private SingleTokenCScanner fStringScanner; /** The preference store */ - private IPreferenceStore fPreferenceStore; + private IPreferenceStore fPreferenceStore; + /** The core preference store */ + private Preferences fCorePreferenceStore; /** The preference change listener */ private PreferenceListener fPreferenceListener= new PreferenceListener(); @@ -54,20 +61,33 @@ public class CTextTools { * Creates a new C text tools collection and eagerly creates * and initializes all members of this collection. */ - public CTextTools(IPreferenceStore store) { + public CTextTools(IPreferenceStore store) { + this(store, null); + } + + /** + * Creates a new C text tools collection and eagerly creates + * and initializes all members of this collection. + */ + public CTextTools(IPreferenceStore store, Preferences coreStore) { if(store == null) { store = CUIPlugin.getDefault().getPreferenceStore(); } fPreferenceStore = store; fPreferenceStore.addPropertyChangeListener(fPreferenceListener); + + fCorePreferenceStore= coreStore; + if (fCorePreferenceStore != null) { + fCorePreferenceStore.addPropertyChangeListener(fPreferenceListener); + } fColorManager= new CColorManager(); fCodeScanner= new CCodeScanner(fColorManager, store); fCppCodeScanner= new CppCodeScanner(fColorManager, store); fPartitionScanner= new FastCPartitionScanner(); - fMultilineCommentScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_MULTI_LINE_COMMENT); - fSinglelineCommentScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_SINGLE_LINE_COMMENT); + fMultilineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_MULTI_LINE_COMMENT); + fSinglelineCommentScanner= new CCommentScanner(fColorManager, store, coreStore, ICColorConstants.C_SINGLE_LINE_COMMENT); fStringScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_STRING); } @@ -100,6 +120,12 @@ public class CTextTools { if (fPreferenceStore != null) { fPreferenceStore.removePropertyChangeListener(fPreferenceListener); fPreferenceStore= null; + + if (fCorePreferenceStore != null) { + fCorePreferenceStore.removePropertyChangeListener(fPreferenceListener); + fCorePreferenceStore= null; + } + fPreferenceListener= null; } } @@ -151,18 +177,18 @@ public class CTextTools { } /** - * Returns a scanner which is configured to scan Java multiline comments. + * Returns a scanner which is configured to scan C multiline comments. * - * @return a Java multiline comment scanner + * @return a C multiline comment scanner */ public RuleBasedScanner getMultilineCommentScanner() { return fMultilineCommentScanner; } /** - * Returns a scanner which is configured to scan Java singleline comments. + * Returns a scanner which is configured to scan C singleline comments. * - * @return a Java singleline comment scanner + * @return a C singleline comment scanner */ public RuleBasedScanner getSinglelineCommentScanner() { return fSinglelineCommentScanner; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java index 2c324b68f7c..729c1f33b3b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICColorConstants.java @@ -26,8 +26,12 @@ public interface ICColorConstants { String C_STRING= "c_string"; //$NON-NLS-1$ /* The color key for everthing in C code for which no other color is specified. */ String C_DEFAULT= "c_default"; //$NON-NLS-1$ - - + + /** + * The color key for task tags in C comments + * (value "c_comment_task_tag"). + */ + String TASK_TAG= "c_comment_task_tag"; //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java index e9a25cbaa60..70fe9d0ccf8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java @@ -13,7 +13,6 @@ import java.io.InputStreamReader; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.IBinary; import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.resources.FileStorage; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java index 9e0b77b1031..7de94146a04 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java @@ -1,9 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ package org.eclipse.cdt.internal.ui.util; -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DragSource; @@ -16,7 +22,9 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Widget; + import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.Assert; @@ -99,8 +107,16 @@ public class SWTUtil { ((GridData)gd).heightHint= getButtonHeigthHint(button); ((GridData)gd).widthHint= getButtonWidthHint(button); } - } + } + + public static int getTableHeightHint(Table table, int rows) { + if (table.getFont().equals(JFaceResources.getDefaultFont())) + table.setFont(JFaceResources.getDialogFont()); + int result= table.getItemHeight() * rows + table.getHeaderHeight(); + if (table.getLinesVisible()) + result+= table.getGridLineWidth() * (rows - 1); + return result; + } } - diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/IStatusChangeListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/IStatusChangeListener.java new file mode 100644 index 00000000000..8f0f417e5e8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/IStatusChangeListener.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.wizards; + +import org.eclipse.core.runtime.IStatus; + +public interface IStatusChangeListener { + + /** + * Notifies this listener that the given status has changed. + * + * @param status the new status + */ + void statusChanged(IStatus status); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/ComboDialogField.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/ComboDialogField.java new file mode 100644 index 00000000000..35d9854dff3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/ComboDialogField.java @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +/** + * Dialog field containing a label and a combo control. + */ +public class ComboDialogField extends DialogField { + + private String fText; + private int fSelectionIndex; + private String[] fItems; + private Combo fComboControl; + private ModifyListener fModifyListener; + private int fFlags; + + public ComboDialogField(int flags) { + super(); + fText= ""; //$NON-NLS-1$ + fItems= new String[0]; + fFlags= flags; + fSelectionIndex= -1; + } + + // ------- layout helpers + + /* + * @see DialogField#doFillIntoGrid + */ + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label= getLabelControl(parent); + label.setLayoutData(gridDataForLabel(1)); + Combo combo= getComboControl(parent); + combo.setLayoutData(gridDataForCombo(nColumns - 1)); + + return new Control[] { label, combo }; + } + + /* + * @see DialogField#getNumberOfControls + */ + public int getNumberOfControls() { + return 2; + } + + protected static GridData gridDataForCombo(int span) { + GridData gd= new GridData(); + gd.horizontalAlignment= GridData.FILL; + gd.grabExcessHorizontalSpace= false; + gd.horizontalSpan= span; + return gd; + } + + // ------- focus methods + + /* + * @see DialogField#setFocus + */ + public boolean setFocus() { + if (isOkToUse(fComboControl)) { + fComboControl.setFocus(); + } + return true; + } + + // ------- ui creation + + /** + * Creates or returns the created combo control. + * @param parent The parent composite or null when the widget has + * already been created. + */ + public Combo getComboControl(Composite parent) { + if (fComboControl == null) { + assertCompositeNotNull(parent); + fModifyListener= new ModifyListener() { + public void modifyText(ModifyEvent e) { + doModifyText(e); + } + }; + SelectionListener selectionListener= new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + doSelectionChanged(e); + } + + public void widgetDefaultSelected(SelectionEvent e) { }; + }; + + fComboControl= new Combo(parent, fFlags); + // moved up due to 1GEUNW2 + fComboControl.setItems(fItems); + if (fSelectionIndex != -1) { + fComboControl.select(fSelectionIndex); + } else { + fComboControl.setText(fText); + } + fComboControl.setFont(parent.getFont()); + fComboControl.addModifyListener(fModifyListener); + fComboControl.addSelectionListener(selectionListener); + fComboControl.setEnabled(isEnabled()); + } + return fComboControl; + } + + private void doModifyText(ModifyEvent e) { + if (isOkToUse(fComboControl)) { + fText= fComboControl.getText(); + fSelectionIndex= fComboControl.getSelectionIndex(); + } + dialogFieldChanged(); + } + + private void doSelectionChanged(SelectionEvent e) { + if (isOkToUse(fComboControl)) { + fItems= fComboControl.getItems(); + fText= fComboControl.getText(); + fSelectionIndex= fComboControl.getSelectionIndex(); + } + dialogFieldChanged(); + } + + // ------ enable / disable management + + /* + * @see DialogField#updateEnableState + */ + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fComboControl)) { + fComboControl.setEnabled(isEnabled()); + } + } + + // ------ text access + + /** + * Gets the combo items. + */ + public String[] getItems() { + return fItems; + } + + /** + * Sets the combo items. Triggers a dialog-changed event. + */ + public void setItems(String[] items) { + fItems= items; + if (isOkToUse(fComboControl)) { + fComboControl.setItems(items); + } + dialogFieldChanged(); + } + + /** + * Gets the text. + */ + public String getText() { + return fText; + } + + /** + * Sets the text. Triggers a dialog-changed event. + */ + public void setText(String text) { + fText= text; + if (isOkToUse(fComboControl)) { + fComboControl.setText(text); + } else { + dialogFieldChanged(); + } + } + + /** + * Selects an item. + */ + public void selectItem(int index) { + if (isOkToUse(fComboControl)) { + fComboControl.select(index); + } else { + if (index >= 0 && index < fItems.length) { + fText= fItems[index]; + fSelectionIndex= index; + } + } + dialogFieldChanged(); + } + + public int getSelectionIndex() { + return fSelectionIndex; + } + + + /** + * Sets the text without triggering a dialog-changed event. + */ + public void setTextWithoutUpdate(String text) { + fText= text; + if (isOkToUse(fComboControl)) { + fComboControl.removeModifyListener(fModifyListener); + fComboControl.setText(text); + fComboControl.addModifyListener(fModifyListener); + } + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/SelectionButtonDialogField.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/SelectionButtonDialogField.java new file mode 100644 index 00000000000..6484096dc2b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/SelectionButtonDialogField.java @@ -0,0 +1,192 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.cdt.internal.ui.util.SWTUtil; + +/** + * Dialog Field containing a single button such as a radio or checkbox button. + */ +public class SelectionButtonDialogField extends DialogField { + + private Button fButton; + private boolean fIsSelected; + private DialogField[] fAttachedDialogFields; + private int fButtonStyle; + + /** + * Creates a selection button. + * Allowed button styles: SWT.RADIO, SWT.CHECK, SWT.TOGGLE, SWT.PUSH + */ + public SelectionButtonDialogField(int buttonStyle) { + super(); + fIsSelected= false; + fAttachedDialogFields= null; + fButtonStyle= buttonStyle; + } + + /** + * Attaches a field to the selection state of the selection button. + * The attached field will be disabled if the selection button is not selected. + */ + public void attachDialogField(DialogField dialogField) { + attachDialogFields(new DialogField[] { dialogField }); + } + + /** + * Attaches fields to the selection state of the selection button. + * The attached fields will be disabled if the selection button is not selected. + */ + public void attachDialogFields(DialogField[] dialogFields) { + fAttachedDialogFields= dialogFields; + for (int i= 0; i < dialogFields.length; i++) { + dialogFields[i].setEnabled(fIsSelected); + } + } + + /** + * Returns true is teh gived field is attached to the selection button. + */ + public boolean isAttached(DialogField editor) { + if (fAttachedDialogFields != null) { + for (int i=0; i < fAttachedDialogFields.length; i++) { + if (fAttachedDialogFields[i] == editor) { + return true; + } + } + } + return false; + } + + // ------- layout helpers + + /* + * @see DialogField#doFillIntoGrid + */ + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Button button= getSelectionButton(parent); + GridData gd= new GridData(); + gd.horizontalSpan= nColumns; + gd.horizontalAlignment= GridData.FILL; + if (fButtonStyle == SWT.PUSH) { + gd.heightHint = SWTUtil.getButtonHeigthHint(button); + gd.widthHint = SWTUtil.getButtonWidthHint(button); + } + + button.setLayoutData(gd); + + return new Control[] { button }; + } + + /* + * @see DialogField#getNumberOfControls + */ + public int getNumberOfControls() { + return 1; + } + + // ------- ui creation + + /** + * Returns the selection button widget. When called the first time, the widget will be created. + * @param The parent composite when called the first time, or null + * after. + */ + public Button getSelectionButton(Composite group) { + if (fButton == null) { + assertCompositeNotNull(group); + + fButton= new Button(group, fButtonStyle); + fButton.setFont(group.getFont()); + fButton.setText(fLabelText); + fButton.setEnabled(isEnabled()); + fButton.setSelection(fIsSelected); + fButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + doWidgetSelected(e); + } + public void widgetSelected(SelectionEvent e) { + doWidgetSelected(e); + } + }); + } + return fButton; + } + + private void doWidgetSelected(SelectionEvent e) { + if (isOkToUse(fButton)) { + changeValue(fButton.getSelection()); + } + } + + private void changeValue(boolean newState) { + if (fIsSelected != newState) { + fIsSelected= newState; + if (fAttachedDialogFields != null) { + boolean focusSet= false; + for (int i= 0; i < fAttachedDialogFields.length; i++) { + fAttachedDialogFields[i].setEnabled(fIsSelected); + if (fIsSelected && !focusSet) { + focusSet= fAttachedDialogFields[i].setFocus(); + } + } + } + dialogFieldChanged(); + } else if (fButtonStyle == SWT.PUSH) { + dialogFieldChanged(); + } + } + + // ------ model access + + /** + * Returns the selection state of the button. + */ + public boolean isSelected() { + return fIsSelected; + } + + /** + * Sets the selection state of the button. + */ + public void setSelection(boolean selected) { + changeValue(selected); + if (isOkToUse(fButton)) { + fButton.setSelection(selected); + } + } + + // ------ enable / disable management + + /* + * @see DialogField#updateEnableState + */ + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fButton)) { + fButton.setEnabled(isEnabled()); + } + } + + + + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java index de071355e4f..5454c5dd54f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java @@ -9,6 +9,7 @@ import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.internal.ui.BuildConsoleManager; @@ -183,7 +184,7 @@ public class CUIPlugin extends AbstractUIPlugin { */ public CTextTools getTextTools() { if (fTextTools == null) - fTextTools = new CTextTools(); + fTextTools = new CTextTools(getPreferenceStore(), CCorePlugin.getDefault().getPluginPreferences()); return fTextTools; } @@ -192,7 +193,7 @@ public class CUIPlugin extends AbstractUIPlugin { */ public AsmTextTools getAsmTextTools() { if (fAsmTextTools == null) - fAsmTextTools = new AsmTextTools(); + fAsmTextTools = new AsmTextTools(getPreferenceStore(), CCorePlugin.getDefault().getPluginPreferences()); return fAsmTextTools; } @@ -263,6 +264,8 @@ public class CUIPlugin extends AbstractUIPlugin { */ protected void initializeDefaultPreferences(final IPreferenceStore store) { super.initializeDefaultPreferences(store); + PreferenceConstants.initializeDefaultValues(store); + runUI(new Runnable() { public void run() { CPluginPreferencePage.initDefaults(store); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java index bdfcba4c30a..3eb5b87630f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java @@ -4,7 +4,12 @@ */ package org.eclipse.cdt.ui; +import org.eclipse.swt.graphics.RGB; + import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; + +import org.eclipse.cdt.internal.ui.text.ICColorConstants; /** * Preference constants used in the JDT-UI preference store. Clients should only read the @@ -18,6 +23,12 @@ public class PreferenceConstants { private PreferenceConstants() { } + + /** + * Preference key suffix for bold text style preference keys. + */ + public static final String EDITOR_BOLD_SUFFIX= "_bold"; //$NON-NLS-1$ + /** * A named preference that controls if comment stubs will be added * automatically to newly created types and methods. @@ -51,7 +62,58 @@ public class PreferenceConstants { *

    */ public static final String EDITOR_SHOW_SEGMENTS= "org.eclipse.cdt.ui.editor.showSegments"; //$NON-NLS-1$ + + /** + * A named preference that holds the color used to render task tags. + *

    + * Value is of type String. A RGB color value encoded as a string + * using class PreferenceConverter + *

    + * + * @see org.eclipse.jface.resource.StringConverter + * @see org.eclipse.jface.preference.PreferenceConverter + */ + public final static String EDITOR_TASK_TAG_COLOR= ICColorConstants.TASK_TAG; + /** + * A named preference that controls whether task tags are rendered in bold. + *

    + * Value is of type Boolean. + *

    + */ + public final static String EDITOR_TASK_TAG_BOLD= ICColorConstants.TASK_TAG + EDITOR_BOLD_SUFFIX; + + /** + * A named preference that controls whether the editor shows task indicators in text (squiggly lines). + *

    + * Value is of type Boolean. + *

    + */ + public final static String EDITOR_TASK_INDICATION= "taskIndication"; //$NON-NLS-1$ + + /** + * A named preference that holds the color used to render task indicators. + *

    + * Value is of type String. A RGB color value encoded as a string + * using class PreferenceConverter + *

    + * + * @see #EDITOR_TASK_INDICATION + * @see org.eclipse.jface.resource.StringConverter + * @see org.eclipse.jface.preference.PreferenceConverter + */ + public final static String EDITOR_TASK_INDICATION_COLOR= "taskIndicationColor"; //$NON-NLS-1$ + + /** + * A named preference that controls whether the overview ruler shows task + * indicators. + *

    + * Value is of type Boolean. + *

    + * @since 2.1 + */ + public final static String EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER= "taskIndicationInOverviewRuler"; //$NON-NLS-1$ + /** * Returns the JDT-UI preference store. * @@ -60,4 +122,18 @@ public class PreferenceConstants { public static IPreferenceStore getPreferenceStore() { return CUIPlugin.getDefault().getPreferenceStore(); } + + /** + * Initializes the given preference store with the default values. + * + * @param store the preference store to be initialized + */ + public static void initializeDefaultValues(IPreferenceStore store) { + store.setDefault(PreferenceConstants.EDITOR_TASK_INDICATION, false); + PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_TASK_INDICATION_COLOR, new RGB(0, 128, 255)); + store.setDefault(PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER, true); + + PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_TASK_TAG_COLOR, new RGB(127, 159, 191)); + store.setDefault(PreferenceConstants.EDITOR_TASK_TAG_BOLD, true); + } } \ No newline at end of file