1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

2005-03-03 Alain Magloire

Part of plan item 79518: for PathEntry variable manager.
	* model/org/eclipse/cdt/internal/core/model/PathEntryManager.java
	* src/org/eclipse/cdt/core/CCorePlugin.java
	* src/org/eclipse/cdt/core/resources/IPathEntryVariableChangeListener.java
	* src/org/eclipse/cdt/core/resources/IPathEntryVariableManager.java
	* src/org/eclipse/cdt/core/resources/PathEntryVariableManager.java
	* src/org/eclipse/cdt/internal/core/PathEntryVariableManager.java
This commit is contained in:
Alain Magloire 2005-03-03 21:59:59 +00:00
parent 9c2e3a9d22
commit 27c8ac0ac3
7 changed files with 553 additions and 9 deletions

View file

@ -1,3 +1,12 @@
2005-03-03 Alain Magloire
Part of plan item 79518: for PathEntry variable manager.
* model/org/eclipse/cdt/internal/core/model/PathEntryManager.java
* src/org/eclipse/cdt/core/CCorePlugin.java
* src/org/eclipse/cdt/core/resources/IPathEntryVariableChangeListener.java
* src/org/eclipse/cdt/core/resources/IPathEntryVariableManager.java
* src/org/eclipse/cdt/core/resources/PathEntryVariableManager.java
* src/org/eclipse/cdt/internal/core/PathEntryVariableManager.java
2005-03-03 Vladimir Hirsl
Small change for enabling generation of path entry container change events.
* model/org/eclipse/cdt/core/model/PathEntryContainerChanged.java

View file

@ -459,7 +459,6 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange
if (hasPathEntryProblemMarkersChange(project, problems)) {
generateMarkers(project, problems);
}
}
// Check for duplication in the sources
@ -1805,11 +1804,9 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange
* Record a new marker denoting a pathentry problem
*/
void createPathEntryProblemMarker(IProject project, ICModelStatus status) {
IMarker marker = null;
int severity = code2Severity(status);
try {
marker = project.createMarker(ICModelMarker.PATHENTRY_PROBLEM_MARKER);
IMarker marker = project.createMarker(ICModelMarker.PATHENTRY_PROBLEM_MARKER);
marker.setAttributes(new String[]{IMarker.MESSAGE, IMarker.SEVERITY, IMarker.LOCATION,
ICModelMarker.PATHENTRY_FILE_FORMAT,}, new Object[]{status.getMessage(), new Integer(severity), "pathentry",//$NON-NLS-1$
"false",//$NON-NLS-1$

View file

@ -25,10 +25,12 @@ import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.core.resources.IPathEntryVariableManager;
import org.eclipse.cdt.core.resources.ScannerProvider;
import org.eclipse.cdt.core.search.SearchEngine;
import org.eclipse.cdt.internal.core.CDTLogWriter;
import org.eclipse.cdt.internal.core.CDescriptorManager;
import org.eclipse.cdt.internal.core.PathEntryVariableManager;
import org.eclipse.cdt.internal.core.model.BufferManager;
import org.eclipse.cdt.internal.core.model.CModelManager;
import org.eclipse.cdt.internal.core.model.DeltaProcessor;
@ -117,6 +119,8 @@ public class CCorePlugin extends Plugin {
private CoreModel fCoreModel;
private PathEntryVariableManager fPathEntryVariableManager;
// -------- static methods --------
static {
@ -215,6 +219,11 @@ public class CCorePlugin extends Plugin {
if (cdtLog != null) {
cdtLog.shutdown();
}
if (fPathEntryVariableManager != null) {
fPathEntryVariableManager.shutdown();
}
savePluginPreferences();
} finally {
super.stop(context);
@ -245,6 +254,9 @@ public class CCorePlugin extends Plugin {
getPluginPreferences().setDefault(PREF_USE_STRUCTURAL_PARSE_MODE, false);
// Start file type manager
fPathEntryVariableManager = new PathEntryVariableManager();
fPathEntryVariableManager.startup();
}
@ -598,6 +610,10 @@ public class CCorePlugin extends Plugin {
return fCoreModel;
}
public IPathEntryVariableManager getPathEntryVariableManager() {
return fPathEntryVariableManager;
}
/**
* @param project
* @return
@ -853,9 +869,9 @@ public class CCorePlugin extends Plugin {
/**
* Configure the plugin with respect to option settings defined in ".options" file
*/
public void configurePluginDebugOptions(){
public void configurePluginDebugOptions() {
if(CCorePlugin.getDefault().isDebugging()){
if(CCorePlugin.getDefault().isDebugging()) {
String option = Platform.getDebugOption(PARSER);
if(option != null) Util.VERBOSE_PARSER = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
@ -903,8 +919,7 @@ public class CCorePlugin extends Plugin {
return getPluginPreferences().getBoolean(PREF_USE_STRUCTURAL_PARSE_MODE);
}
public CDOM getDOM()
{
public CDOM getDOM() {
return CDOM.getInstance();
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2000, 2004 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
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.resources;
import java.util.EventListener;
/**
* An interface to be implemented by objects interested in path variable
* creation, removal and value change events.
*
* <p>Clients may implement this interface.</p>
*
* @since 3.0
*/
public interface IPathEntryVariableChangeListener extends EventListener {
/**
* Notification that a path variable has changed.
* <p>
* This method is called when a path variable is added, removed or has its value
* changed in the observed <code>IPathVariableManager</code> object.
* </p>
*
* @param event the path variable change event object describing which variable
* changed and how
* @see IPathEntryVariableManager#addChangeListener(IPathVariableChangeListener)
* @see IPathEntryVariableManager#removeChangeListener(IPathVariableChangeListener)
* @see PathEntryVariableChangeEvent
*/
public void pathVariableChanged(PathEntryVariableChangeEvent event);
}

View file

@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2000, 2004 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
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.resources;
import org.eclipse.core.runtime.CoreException;
/**
* Manages a collection of variables
* @since 3.0
*/
public interface IPathEntryVariableManager {
/**
* Sets the variable with the given name to be the specified value.
* Depending on the value given and if the variable is currently defined
* or not, there are several possible outcomes for this operation:
* <p>
* <ul>
* <li>A new variable will be created, if there is no variable defined with
* the given name, and the given value is not <code>null</code>.
* </li>
*
* <li>The referred variable's value will be changed, if it already exists
* and the given value is not <code>null</code>.</li>
*
* <li>The referred variable will be removed, if a variable with the given
* name is currently defined and the given value is <code>null</code>.
* </li>
*
* <li>The call will be ignored, if a variable with the given name is not
* currently defined and the given value is <code>null</code>, or if it is
* defined but the given value is equal to its current value.
* </li>
* </ul>
* <p>If a variable is effectively changed, created or removed by a call to
* this method, notification will be sent to all registered listeners.</p>
*
* @param name the name of the variable
* @param value the value for the variable (may be <code>null</code>)
* @exception CoreException if this method fails. Reasons include:
* <ul>
* <li>The variable name is not valid</li>
* <li>The variable value is relative</li>
* </ul>
*/
public void setValue(String name, String value) throws CoreException;
/**
* Returns the value of the variable with the given name. If there is
* no variable defined with the given name, returns <code>null</code>.
*
* @param name the name of the variable to return the value for
* @return the value for the variable, or <code>null</code> if there is no
* variable defined with the given name
*/
public String getValue(String name);
/**
* Returns an array containing all defined variable names.
*
* @return an array containing all defined variable names
*/
public String[] getVariableNames();
/**
* Registers the given listener to receive notification of changes to
* variables. The listener will be notified whenever a variable has been
* added, removed or had its value changed. Has no effect if an identical
* variable change listener is already registered.
*
* @param listener the listener
* @see IPathEntryVariableChangeListener
*/
public void addChangeListener(IPathEntryVariableChangeListener listener);
/**
* Removes the given variable change listener from the listeners list.
* Has no effect if an identical listener is not registered.
*
* @param listener the listener
* @see IPathEntryVariableChangeListener
*/
public void removeChangeListener(IPathEntryVariableChangeListener listener);
/**
* Resolves a <code>String</code> potentially containing a
* variable reference, replacing the variable reference
* (if any) with the variable's value (which is a concrete absolute path).
* <p>
* If the given String is <code>null</code> then <code>null</code> will be
* returned. In all other cases the result will be non-<code>null</code>.
* </p>
*
* <p>
* For example, consider the following collection of path variables:
* </p>
* <ul>
* <li>TEMP = c:/temp</li>
* <li>BACKUP = /tmp/backup</li>
* </ul>
* <p>The following paths would be resolved as:
* <p>c:/bin => c:/bin</p>
* <p>c:${TEMP} => c:/temp</p>
* <p>/TEMP => /TEMP</p>
* <p>${TEMP}/foo => /temp/foo</p>
* <p>${BACKUP} => /tmp/backup</p>
* <p>${BACKUP}/bar.txt => /tmp/backup/bar.txt</p>
* <p>SOMEPATH/foo => SOMEPATH/foo</p></p>
*
* @param path the path to be resolved
* @return the resolved path or <code>null</code>
*/
public String resolvePath(String path);
/**
* Returns <code>true</code> if the given variable is defined and
* <code>false</code> otherwise. Returns <code>false</code> if the given
* name is not a valid path variable name.
*
* @param name the variable's name
* @return <code>true</code> if the variable exists, <code>false</code>
* otherwise
*/
public boolean isDefined(String name);
}

View file

@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (c) 2000, 2004 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
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.resources;
import java.util.EventObject;
/**
* Describes a change in path variable.
*/
public class PathEntryVariableChangeEvent extends EventObject {
private static final long serialVersionUID = 1L;
/** Event type constant (value = 1) that denotes a value change . */
public final static int VARIABLE_CHANGED = 1;
/** Event type constant (value = 2) that denotes a variable creation. */
public final static int VARIABLE_CREATED = 2;
/** Event type constant (value = 3) that denotes a variable deletion. */
public final static int VARIABLE_DELETED = 3;
/**
* The name of the changed variable.
*/
private String variableName;
/**
* The value of the changed variable (may be null).
*/
private String value;
/** The event type. */
private int type;
/**
* Constructor for this class.
*/
public PathEntryVariableChangeEvent(IPathEntryVariableManager source, String variableName, String value, int type) {
super(source);
if (type < VARIABLE_CHANGED || type > VARIABLE_DELETED)
throw new IllegalArgumentException("Invalid event type: " + type); //$NON-NLS-1$
this.variableName = variableName;
this.value = value;
this.type = type;
}
public String getValue() {
return value;
}
public String getVariableName() {
return variableName;
}
public int getType() {
return type;
}
/**
* Return a string representation of this object.
*/
public String toString() {
String[] typeStrings = {"VARIABLE_CHANGED", "VARIABLE_CREATED", "VARIABLE_DELETED"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
StringBuffer sb = new StringBuffer(getClass().getName());
sb.append("[variable = "); //$NON-NLS-1$
sb.append(variableName);
sb.append(", type = "); //$NON-NLS-1$
sb.append(typeStrings[type - 1]);
if (type != VARIABLE_DELETED) {
sb.append(", value = "); //$NON-NLS-1$
sb.append(value);
}
sb.append("]"); //$NON-NLS-1$
return sb.toString();
}
}

View file

@ -0,0 +1,257 @@
/*******************************************************************************
* Copyright (c) 2000, 2004 QNX Software Systems 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
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.resources.IPathEntryVariableChangeListener;
import org.eclipse.cdt.core.resources.IPathEntryVariableManager;
import org.eclipse.cdt.core.resources.PathEntryVariableChangeEvent;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
/**
* Core's implementation of IPathEntryVariableManager.
*/
public class PathEntryVariableManager implements IPathEntryVariableManager {
private Set listeners;
private Preferences preferences;
static final String VARIABLE_PREFIX = "pathEntryVariable."; //$NON-NLS-1$
/**
* Constructor for the class.
*/
public PathEntryVariableManager() {
this.listeners = Collections.synchronizedSet(new HashSet());
this.preferences = CCorePlugin.getDefault().getPluginPreferences();
}
/**
* Note that if a user changes the key in the preferences file to be invalid
* and then calls #getValue using that key, they will get the value back for
* that. But then if they try and call #setValue using the same key it will throw
* an exception. We may want to revisit this behaviour in the future.
*
* @see org.eclipse.core.resources.IPathEntryVariableManager#getValue(String)
*/
public String getValue(String varName) {
String key = getKeyForName(varName);
String value = preferences.getString(key);
return value.length() == 0 ? null : value;
}
/**
* @see org.eclipse.core.resources.IPathEntryVariableManager#setValue(String, IPath)
*/
public void setValue(String varName, String newValue) throws CoreException {
int eventType;
// read previous value and set new value atomically in order to generate the right event
synchronized (this) {
String currentValue = getValue(varName);
boolean variableExists = currentValue != null;
if (!variableExists && newValue == null) {
return;
}
if (variableExists && currentValue.equals(newValue)) {
return;
}
if (newValue == null) {
preferences.setToDefault(getKeyForName(varName));
eventType = PathEntryVariableChangeEvent.VARIABLE_DELETED;
} else {
preferences.setValue(getKeyForName(varName), newValue);
eventType = variableExists ? PathEntryVariableChangeEvent.VARIABLE_CHANGED : PathEntryVariableChangeEvent.VARIABLE_CREATED;
}
}
// notify listeners from outside the synchronized block to avoid deadlocks
fireVariableChangeEvent(varName, newValue, eventType);
}
/**
* Return a key to use in the Preferences.
*/
private String getKeyForName(String varName) {
return VARIABLE_PREFIX + varName;
}
/**
* @see org.eclipse.core.resources.IPathEntryVariableManager#resolvePath(IPath)
*/
public String resolvePath(String variable) {
if (variable == null || variable.length() == 0 || variable.indexOf('$') == -1) {
return variable;
}
String value = expandVariable(variable);
return value == null ? variable : value;
}
/**
* Fires a property change event corresponding to a change to the
* current value of the variable with the given name.
*
* @param name the name of the variable, to be used as the variable
* in the event object
* @param value the current value of the path variable or <code>null</code> if
* the variable was deleted
* @param type one of <code>IPathVariableChangeEvent.VARIABLE_CREATED</code>,
* <code>PathEntryVariableChangeEvent.VARIABLE_CHANGED</code>, or
* <code>PathEntryVariableChangeEvent.VARIABLE_DELETED</code>
* @see PathEntryVariableChangeEvent
* @see PathEntryVariableChangeEvent#VARIABLE_CREATED
* @see PathEntryVariableChangeEvent#VARIABLE_CHANGED
* @see PathEntryVariableChangeEvent#VARIABLE_DELETED
*/
private void fireVariableChangeEvent(String name, String value, int type) {
if (this.listeners.size() == 0)
return;
// use a separate collection to avoid interference of simultaneous additions/removals
Object[] listenerArray = this.listeners.toArray();
final PathEntryVariableChangeEvent pve = new PathEntryVariableChangeEvent(this, name, value, type);
for (int i = 0; i < listenerArray.length; ++i) {
final IPathEntryVariableChangeListener l = (IPathEntryVariableChangeListener) listenerArray[i];
ISafeRunnable job = new ISafeRunnable() {
public void handleException(Throwable exception) {
// already being logged in Platform#run()
}
public void run() throws Exception {
l.pathVariableChanged(pve);
}
};
Platform.run(job);
}
}
/**
* @see org.eclipse.core.resources.IPathVariableManager#getPathVariableNames()
*/
public String[] getVariableNames() {
List result = new LinkedList();
String[] names = preferences.propertyNames();
for (int i = 0; i < names.length; i++) {
if (names[i].startsWith(VARIABLE_PREFIX)) {
String key = names[i].substring(VARIABLE_PREFIX.length());
result.add(key);
}
}
return (String[]) result.toArray(new String[result.size()]);
}
/**
* @see org.eclipse.core.resources.
* IPathEntryVariableManager#addChangeListener(IPathEntryVariableChangeListener)
*/
public void addChangeListener(IPathEntryVariableChangeListener listener) {
listeners.add(listener);
}
/**
* @see org.eclipse.core.resources.
* IPathEntryVariableManager#removeChangeListener(IPathEntryVariableChangeListener)
*/
public void removeChangeListener(IPathEntryVariableChangeListener listener) {
listeners.remove(listener);
}
/**
* @see org.eclipse.core.resources.IPathVariableManager#isDefined(String)
*/
public boolean isDefined(String varName) {
return getValue(varName) != null;
}
public void startup() {
}
public void shutdown() {
}
/**
* Expand the variable with the format ${key}. example:
* with variable HOME=/foobar
* ${HOME}/project
* The the return value will be /foobar/project.
*/
protected String expandVariable(String variable) {
StringBuffer sb = new StringBuffer();
StringBuffer param = new StringBuffer();
char prev = '\n';
char ch = prev;
boolean inMacro = false;
boolean inSingleQuote = false;
for (int i = 0; i < variable.length(); i++) {
ch = variable.charAt(i);
switch (ch) {
case '\'':
if (prev != '\\') {
inSingleQuote = !inSingleQuote;
}
break;
case '$' :
if (!inSingleQuote && prev != '\\') {
if (i < variable.length() && variable.indexOf('}', i) > 0) {
char c = variable.charAt(i + 1);
if (c == '{') {
param.setLength(0);
inMacro = true;
prev = ch;
continue;
}
}
}
break;
case '}' :
if (inMacro) {
inMacro = false;
String p = param.toString();
String v = getValue(p);
if (v != null) {
sb.append(v);
}
param.setLength(0);
/* Skip the trailing } */
prev = ch;
continue;
}
break;
} /* switch */
if (!inMacro) {
sb.append(ch);
} else {
/* Do not had the '{' */
if (!(ch == '{' && prev == '$')) {
param.append(ch);
}
}
prev = (ch == '\\' && prev == '\\') ? '\n' : ch;
} /* for */
return sb.toString();
}
}