mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Merge remote-tracking branch 'cdt/master' into sd90
This commit is contained in:
commit
0df3dfbbbc
55 changed files with 2627 additions and 679 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2010 IBM Corporation and others.
|
* Copyright (c) 2004, 2011 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -58,7 +58,6 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider {
|
||||||
private static final String EXTERNAL_SI_PROVIDER_ERROR = "ExternalScannerInfoProvider.Provider_Error"; //$NON-NLS-1$
|
private static final String EXTERNAL_SI_PROVIDER_ERROR = "ExternalScannerInfoProvider.Provider_Error"; //$NON-NLS-1$
|
||||||
private static final String GMAKE_ERROR_PARSER_ID = "org.eclipse.cdt.core.GmakeErrorParser"; //$NON-NLS-1$
|
private static final String GMAKE_ERROR_PARSER_ID = "org.eclipse.cdt.core.GmakeErrorParser"; //$NON-NLS-1$
|
||||||
private static final String PREF_CONSOLE_ENABLED = "org.eclipse.cdt.make.core.scanner.discovery.console.enabled"; //$NON-NLS-1$
|
private static final String PREF_CONSOLE_ENABLED = "org.eclipse.cdt.make.core.scanner.discovery.console.enabled"; //$NON-NLS-1$
|
||||||
private static final String LANG_ENV_VAR = "LANG"; //$NON-NLS-1$
|
|
||||||
private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
|
private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
private static final String PATH_ENV = "PATH"; //$NON-NLS-1$
|
private static final String PATH_ENV = "PATH"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
@ -262,21 +261,19 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider {
|
||||||
|
|
||||||
private Properties getEnvMap(ICommandLauncher launcher, Properties initialEnv) {
|
private Properties getEnvMap(ICommandLauncher launcher, Properties initialEnv) {
|
||||||
// Set the environmennt, some scripts may need the CWD var to be set.
|
// Set the environmennt, some scripts may need the CWD var to be set.
|
||||||
Properties props = initialEnv != null ? initialEnv : launcher.getEnvironment();
|
Properties props = initialEnv != null ? initialEnv : launcher.getEnvironment();
|
||||||
|
|
||||||
if (fWorkingDirectory != null) {
|
if (fWorkingDirectory != null) {
|
||||||
props.put("CWD", fWorkingDirectory.toOSString()); //$NON-NLS-1$
|
props.put("CWD", fWorkingDirectory.toOSString()); //$NON-NLS-1$
|
||||||
props.put("PWD", fWorkingDirectory.toOSString()); //$NON-NLS-1$
|
props.put("PWD", fWorkingDirectory.toOSString()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
// On POSIX (Linux, UNIX) systems reset LANG variable to English with
|
// On POSIX (Linux, UNIX) systems reset LANG variable to English with
|
||||||
// UTF-8 encoding
|
// UTF-8 encoding since GNU compilers can handle only UTF-8 characters.
|
||||||
// since GNU compilers can handle only UTF-8 characters. English language is chosen
|
// Include paths with locale characters will be handled properly regardless
|
||||||
// beacuse GNU compilers inconsistently handle different locales when generating
|
// of the language as long as the encoding is set to UTF-8.
|
||||||
// output of the 'gcc -v' command. Include paths with locale characters will be
|
// English language is chosen because parser relies on English messages
|
||||||
// handled properly regardless of the language as long as the encoding is set to UTF-8.
|
// in the output of the 'gcc -v' command.
|
||||||
if (props.containsKey(LANG_ENV_VAR)) {
|
props.put("LC_ALL", "en_US.UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
props.put(LANG_ENV_VAR, "en_US.UTF-8"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,94 +1,93 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2010 IBM Corporation and others.
|
* Copyright (c) 2004, 2011 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM - Initial API and implementation
|
* IBM - Initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.make.internal.core.scannerconfig2;
|
package org.eclipse.cdt.make.internal.core.scannerconfig2;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCProjectNature;
|
import org.eclipse.cdt.core.CCProjectNature;
|
||||||
import org.eclipse.cdt.core.CProjectNature;
|
import org.eclipse.cdt.core.CProjectNature;
|
||||||
import org.eclipse.cdt.make.core.MakeCorePlugin;
|
import org.eclipse.cdt.make.core.MakeCorePlugin;
|
||||||
import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes;
|
import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes;
|
||||||
import org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCScannerConfigUtil;
|
import org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCScannerConfigUtil;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a command to retrieve compiler intrinsic scanner info from 'specs' file.
|
* Runs a command to retrieve compiler intrinsic scanner info from 'specs' file.
|
||||||
*
|
*
|
||||||
* @author vhirsl
|
* @author vhirsl
|
||||||
*/
|
*/
|
||||||
public class GCCSpecsRunSIProvider extends DefaultRunSIProvider {
|
public class GCCSpecsRunSIProvider extends DefaultRunSIProvider {
|
||||||
|
/* (non-Javadoc)
|
||||||
/* (non-Javadoc)
|
* @see org.eclipse.cdt.make.internal.core.scannerconfig2.DefaultRunSIProvider#initialize()
|
||||||
* @see org.eclipse.cdt.make.internal.core.scannerconfig2.DefaultRunSIProvider#initialize()
|
*/
|
||||||
*/
|
@Override
|
||||||
@Override
|
protected boolean initialize() {
|
||||||
protected boolean initialize() {
|
boolean rc = super.initialize();
|
||||||
boolean rc = super.initialize();
|
|
||||||
|
if (rc) {
|
||||||
if (rc) {
|
String targetFile = "dummy"; //$NON-NLS-1$
|
||||||
String targetFile = "dummy"; //$NON-NLS-1$
|
IProject project = resource.getProject();
|
||||||
IProject project = resource.getProject();
|
try {
|
||||||
try {
|
if (project.hasNature(CCProjectNature.CC_NATURE_ID)) {
|
||||||
if (project.hasNature(CCProjectNature.CC_NATURE_ID)) {
|
targetFile = GCCScannerConfigUtil.CPP_SPECS_FILE;
|
||||||
targetFile = GCCScannerConfigUtil.CPP_SPECS_FILE;
|
}
|
||||||
}
|
else if (project.hasNature(CProjectNature.C_NATURE_ID)) {
|
||||||
else if (project.hasNature(CProjectNature.C_NATURE_ID)) {
|
targetFile = GCCScannerConfigUtil.C_SPECS_FILE;
|
||||||
targetFile = GCCScannerConfigUtil.C_SPECS_FILE;
|
}
|
||||||
}
|
// replace string variables in compile arguments
|
||||||
// replace string variables in compile arguments
|
// TODO Vmir - use string variable replacement
|
||||||
// TODO Vmir - use string variable replacement
|
for (int i = 0; i < fCompileArguments.length; ++i) {
|
||||||
for (int i = 0; i < fCompileArguments.length; ++i) {
|
fCompileArguments[i] = fCompileArguments[i].replaceAll("\\$\\{plugin_state_location\\}", //$NON-NLS-1$
|
||||||
fCompileArguments[i] = fCompileArguments[i].replaceAll("\\$\\{plugin_state_location\\}", //$NON-NLS-1$
|
MakeCorePlugin.getWorkingDirectory().toString());
|
||||||
MakeCorePlugin.getWorkingDirectory().toString());
|
fCompileArguments[i] = fCompileArguments[i].replaceAll("\\$\\{specs_file\\}", targetFile); //$NON-NLS-1$
|
||||||
fCompileArguments[i] = fCompileArguments[i].replaceAll("\\$\\{specs_file\\}", targetFile); //$NON-NLS-1$
|
}
|
||||||
}
|
} catch (CoreException e) {
|
||||||
} catch (CoreException e) {
|
//TODO VMIR better error handling
|
||||||
//TODO VMIR better error handling
|
MakeCorePlugin.log(e.getStatus());
|
||||||
MakeCorePlugin.log(e.getStatus());
|
rc = false;
|
||||||
rc = false;
|
}
|
||||||
}
|
}
|
||||||
}
|
return rc;
|
||||||
return rc;
|
}
|
||||||
}
|
|
||||||
|
/* (non-Javadoc)
|
||||||
/* (non-Javadoc)
|
* @see org.eclipse.cdt.make.internal.core.scannerconfig2.DefaultRunSIProvider#prepareArguments(boolean)
|
||||||
* @see org.eclipse.cdt.make.internal.core.scannerconfig2.DefaultRunSIProvider#prepareArguments(boolean)
|
*/
|
||||||
*/
|
@Override
|
||||||
@Override
|
protected String[] prepareArguments(boolean isDefaultCommand) {
|
||||||
protected String[] prepareArguments(boolean isDefaultCommand) {
|
if (collector == null)
|
||||||
if (collector == null)
|
return fCompileArguments;
|
||||||
return fCompileArguments;
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@SuppressWarnings("unchecked")
|
List<String> tso = collector.getCollectedScannerInfo(resource.getProject(), ScannerInfoTypes.TARGET_SPECIFIC_OPTION);
|
||||||
List<String> tso = collector.getCollectedScannerInfo(resource.getProject(), ScannerInfoTypes.TARGET_SPECIFIC_OPTION);
|
if (tso == null || tso.size() == 0) {
|
||||||
if (tso == null || tso.size() == 0) {
|
return fCompileArguments;
|
||||||
return fCompileArguments;
|
}
|
||||||
}
|
|
||||||
|
String[] rv = null;
|
||||||
String[] rv = null;
|
// commandArguments may have multiple arguments; tokenizing
|
||||||
// commandArguments may have multiple arguments; tokenizing
|
int nTokens = 0;
|
||||||
int nTokens = 0;
|
if (fCompileArguments != null && fCompileArguments.length > 0) {
|
||||||
if (fCompileArguments != null && fCompileArguments.length > 0) {
|
nTokens = fCompileArguments.length;
|
||||||
nTokens = fCompileArguments.length;
|
rv = new String[nTokens + tso.size()];
|
||||||
rv = new String[nTokens + tso.size()];
|
System.arraycopy(fCompileArguments, 0, rv, 0, nTokens);
|
||||||
System.arraycopy(fCompileArguments, 0, rv, 0, nTokens);
|
}
|
||||||
}
|
else {
|
||||||
else {
|
rv = new String[tso.size()];
|
||||||
rv = new String[tso.size()];
|
}
|
||||||
}
|
for (int i = 0; i < tso.size(); ++i) {
|
||||||
for (int i = 0; i < tso.size(); ++i) {
|
rv[nTokens + i] = tso.get(i);
|
||||||
rv[nTokens + i] = tso.get(i);
|
}
|
||||||
}
|
return rv;
|
||||||
return rv;
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -338,9 +338,9 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
|
||||||
|
|
||||||
if (parentConfig != null) {
|
if (parentConfig != null) {
|
||||||
name = parentConfig.getName();
|
name = parentConfig.getName();
|
||||||
// If this contructor is called to clone an existing
|
// If this constructor is called to clone an existing
|
||||||
// configuration, the parent of the parent should be stored.
|
// configuration, the parent of the parent should be stored.
|
||||||
// As of 2.1, there is still one single level of inheritence to
|
// As of 2.1, there is still one single level of inheritance to
|
||||||
// worry about
|
// worry about
|
||||||
parent = parentConfig.getParent() == null ? parentConfig : parentConfig.getParent();
|
parent = parentConfig.getParent() == null ? parentConfig : parentConfig.getParent();
|
||||||
}
|
}
|
||||||
|
@ -486,8 +486,8 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
|
||||||
|
|
||||||
// if(!baseCfg.isExtensionConfig)
|
// if(!baseCfg.isExtensionConfig)
|
||||||
// cloneChildren = true;
|
// cloneChildren = true;
|
||||||
// If this contructor is called to clone an existing
|
// If this constructor is called to clone an existing
|
||||||
// configuration, the parent of the cloning config should be stored.
|
// configuration, the parent of the cloning config should be stored.
|
||||||
parent = baseCfg.isExtensionConfig || baseCfg.getParent() == null ? baseCfg : baseCfg.getParent();
|
parent = baseCfg.isExtensionConfig || baseCfg.getParent() == null ? baseCfg : baseCfg.getParent();
|
||||||
|
|
||||||
// Copy the remaining attributes
|
// Copy the remaining attributes
|
||||||
|
@ -634,8 +634,8 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
|
||||||
|
|
||||||
if(!cloneConfig.isExtensionConfig)
|
if(!cloneConfig.isExtensionConfig)
|
||||||
cloneChildren = true;
|
cloneChildren = true;
|
||||||
// If this contructor is called to clone an existing
|
// If this constructor is called to clone an existing
|
||||||
// configuration, the parent of the cloning config should be stored.
|
// configuration, the parent of the cloning config should be stored.
|
||||||
parent = cloneConfig.isExtensionConfig || cloneConfig.getParent() == null ? cloneConfig : cloneConfig.getParent();
|
parent = cloneConfig.isExtensionConfig || cloneConfig.getParent() == null ? cloneConfig : cloneConfig.getParent();
|
||||||
parentId = parent.getId();
|
parentId = parent.getId();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2005, 2010 Intel Corporation and others.
|
* Copyright (c) 2005, 2011 Intel Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -22,27 +22,50 @@ import org.eclipse.cdt.managedbuilder.internal.envvar.BuildEnvVar;
|
||||||
*/
|
*/
|
||||||
public class GnuCygwinConfigurationEnvironmentSupplier implements
|
public class GnuCygwinConfigurationEnvironmentSupplier implements
|
||||||
IConfigurationEnvironmentVariableSupplier {
|
IConfigurationEnvironmentVariableSupplier {
|
||||||
|
|
||||||
|
private static final String PATH = "PATH"; //$NON-NLS-1$
|
||||||
|
private static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$
|
||||||
|
private static final String PROPERTY_DELIMITER = "path.separator"; //$NON-NLS-1$
|
||||||
|
private static final String PROPERTY_OSNAME = "os.name"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String LANG = "LANG"; //$NON-NLS-1$
|
||||||
|
private static final String LC_ALL = "LC_ALL"; //$NON-NLS-1$
|
||||||
|
private static final String LC_MESSAGES = "LC_MESSAGES"; //$NON-NLS-1$
|
||||||
|
|
||||||
static final String VARNAME = "PATH"; //$NON-NLS-1$
|
|
||||||
static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$
|
|
||||||
static final String PROPERTY_DELIMITER = "path.separator"; //$NON-NLS-1$
|
|
||||||
static final String PROPERTY_OSNAME = "os.name"; //$NON-NLS-1$
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier#getVariable(java.lang.String, org.eclipse.cdt.managedbuilder.core.IConfiguration, org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider)
|
* @see org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier#getVariable(java.lang.String, org.eclipse.cdt.managedbuilder.core.IConfiguration, org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IBuildEnvironmentVariable getVariable(String variableName,
|
public IBuildEnvironmentVariable getVariable(String variableName,
|
||||||
IConfiguration configuration, IEnvironmentVariableProvider provider) {
|
IConfiguration configuration, IEnvironmentVariableProvider provider) {
|
||||||
|
|
||||||
|
if (variableName == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (!System.getProperty(PROPERTY_OSNAME).toLowerCase().startsWith("windows ")) //$NON-NLS-1$
|
if (!System.getProperty(PROPERTY_OSNAME).toLowerCase().startsWith("windows ")) //$NON-NLS-1$
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (variableName.equalsIgnoreCase(PATH)) {
|
||||||
|
String p = CygwinPathResolver.getBinPath();
|
||||||
|
if (p != null)
|
||||||
|
return new BuildEnvVar(PATH, p.replace('/','\\'), IBuildEnvironmentVariable.ENVVAR_PREPEND, System.getProperty(PROPERTY_DELIMITER, DELIMITER_UNIX));
|
||||||
|
} else if (variableName.equalsIgnoreCase(LANG)) {
|
||||||
|
// Workaround for not being able to select encoding for CDT console -> change codeset to Latin1
|
||||||
|
String langValue = System.getenv(LANG);
|
||||||
|
if (langValue == null || langValue.length() == 0)
|
||||||
|
langValue = System.getenv(LC_ALL);
|
||||||
|
if (langValue == null || langValue.length() == 0)
|
||||||
|
langValue = System.getenv(LC_MESSAGES);
|
||||||
|
if (langValue != null && langValue.length() > 0)
|
||||||
|
// langValue is [language[_territory][.codeset][@modifier]], i.e. "en_US.UTF-8@dict"
|
||||||
|
// we replace codeset with Latin1 as CDT console garbles UTF
|
||||||
|
// and ignore modifier which is not used by LANG
|
||||||
|
langValue = langValue.replaceFirst("([^.@]*)(\\..*)?(@.*)?", "$1.ISO-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
else
|
||||||
|
langValue = "C.ISO-8859-1"; //$NON-NLS-1$
|
||||||
|
|
||||||
if (variableName == null) return null;
|
return new BuildEnvVar(LANG, langValue);
|
||||||
if (!VARNAME.equalsIgnoreCase(variableName)) return null;
|
}
|
||||||
|
|
||||||
String p = CygwinPathResolver.getBinPath();
|
|
||||||
if (p != null)
|
|
||||||
return new BuildEnvVar(VARNAME, p.replace('/','\\'), IBuildEnvironmentVariable.ENVVAR_PREPEND, System.getProperty(PROPERTY_DELIMITER, DELIMITER_UNIX));
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,9 +76,13 @@ public class GnuCygwinConfigurationEnvironmentSupplier implements
|
||||||
public IBuildEnvironmentVariable[] getVariables(
|
public IBuildEnvironmentVariable[] getVariables(
|
||||||
IConfiguration configuration, IEnvironmentVariableProvider provider) {
|
IConfiguration configuration, IEnvironmentVariableProvider provider) {
|
||||||
|
|
||||||
IBuildEnvironmentVariable[] tmp = new IBuildEnvironmentVariable[1];
|
IBuildEnvironmentVariable varLang = getVariable(LANG, configuration, provider);
|
||||||
tmp[0] = getVariable(VARNAME, configuration, provider);
|
IBuildEnvironmentVariable varPath = getVariable(PATH, configuration, provider);
|
||||||
if (tmp[0] != null) return tmp;
|
|
||||||
return null;
|
if (varPath != null) {
|
||||||
|
return new IBuildEnvironmentVariable[] {varLang, varPath};
|
||||||
|
} else {
|
||||||
|
return new IBuildEnvironmentVariable[] {varLang};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,8 +98,8 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker {
|
||||||
|
|
||||||
public int visit(IASTExpression expression) {
|
public int visit(IASTExpression expression) {
|
||||||
if (!constructorsStack.empty() && expression instanceof IASTFunctionCallExpression) {
|
if (!constructorsStack.empty() && expression instanceof IASTFunctionCallExpression) {
|
||||||
Set<IField> actualContructorFields = constructorsStack.peek();
|
Set<IField> actualConstructorFields = constructorsStack.peek();
|
||||||
if (!actualContructorFields.isEmpty()) {
|
if (!actualConstructorFields.isEmpty()) {
|
||||||
boolean skipCurrentConstructor = false;
|
boolean skipCurrentConstructor = false;
|
||||||
IASTFunctionCallExpression fCall = (IASTFunctionCallExpression)expression;
|
IASTFunctionCallExpression fCall = (IASTFunctionCallExpression)expression;
|
||||||
IASTExpression fNameExp = fCall.getFunctionNameExpression();
|
IASTExpression fNameExp = fCall.getFunctionNameExpression();
|
||||||
|
@ -108,7 +108,7 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker {
|
||||||
IBinding fBinding = fName.getName().resolveBinding();
|
IBinding fBinding = fName.getName().resolveBinding();
|
||||||
if (fBinding instanceof ICPPMethod) {
|
if (fBinding instanceof ICPPMethod) {
|
||||||
ICPPMethod method = (ICPPMethod)fBinding;
|
ICPPMethod method = (ICPPMethod)fBinding;
|
||||||
ICompositeType constructorOwner = actualContructorFields.iterator().next().getCompositeTypeOwner();
|
ICompositeType constructorOwner = actualConstructorFields.iterator().next().getCompositeTypeOwner();
|
||||||
if (constructorOwner == method.getClassOwner() && !method.getType().isConst()) {
|
if (constructorOwner == method.getClassOwner() && !method.getType().isConst()) {
|
||||||
skipCurrentConstructor = true;
|
skipCurrentConstructor = true;
|
||||||
}
|
}
|
||||||
|
@ -152,12 +152,12 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker {
|
||||||
|
|
||||||
public int visit(IASTName name) {
|
public int visit(IASTName name) {
|
||||||
if (!constructorsStack.empty()) {
|
if (!constructorsStack.empty()) {
|
||||||
Set<IField> actualContructorFields = constructorsStack.peek();
|
Set<IField> actualConstructorFields = constructorsStack.peek();
|
||||||
if (!actualContructorFields.isEmpty()) {
|
if (!actualConstructorFields.isEmpty()) {
|
||||||
IBinding binding = name.resolveBinding();
|
IBinding binding = name.resolveBinding();
|
||||||
if (actualContructorFields.contains(binding)) {
|
if (actualConstructorFields.contains(binding)) {
|
||||||
if ((CPPVariableReadWriteFlags.getReadWriteFlags(name) & PDOMName.WRITE_ACCESS) != 0) {
|
if ((CPPVariableReadWriteFlags.getReadWriteFlags(name) & PDOMName.WRITE_ACCESS) != 0) {
|
||||||
actualContructorFields.remove(binding);
|
actualConstructorFields.remove(binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class ClassMembersInitializationCheckerTest extends CheckerTestCase {
|
||||||
// int m;
|
// int m;
|
||||||
// C() { m = 0; } // No warnings.
|
// C() { m = 0; } // No warnings.
|
||||||
// };
|
// };
|
||||||
public void testAssignmentsInContructorShouldBeChecked() {
|
public void testAssignmentsInConstructorShouldBeChecked() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ public class ClassMembersInitializationCheckerTest extends CheckerTestCase {
|
||||||
// int i1, i2;
|
// int i1, i2;
|
||||||
// };
|
// };
|
||||||
// C::C() : i1(0) {} // 1 warning for: i2.
|
// C::C() : i1(0) {} // 1 warning for: i2.
|
||||||
public void testExternalContructorHandling() {
|
public void testExternalConstructorHandling() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(5);
|
checkErrorLines(5);
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ public class ClassMembersInitializationCheckerTest extends CheckerTestCase {
|
||||||
// T2 t2;
|
// T2 t2;
|
||||||
// };
|
// };
|
||||||
// C::C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
// C::C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
||||||
public void testExternalContructorOfTemplateClassHandling() {
|
public void testExternalConstructorOfTemplateClassHandling() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(8);
|
checkErrorLines(8);
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ public class ClassMembersInitializationCheckerTest extends CheckerTestCase {
|
||||||
// };
|
// };
|
||||||
// template <typename T>
|
// template <typename T>
|
||||||
// C::C() : i1(0) {} // 1 warning for: i2.
|
// C::C() : i1(0) {} // 1 warning for: i2.
|
||||||
public void testExternalTemplateContructorHandling() {
|
public void testExternalTemplateConstructorHandling() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(7);
|
checkErrorLines(7);
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ public class ClassMembersInitializationCheckerTest extends CheckerTestCase {
|
||||||
// template <typename T1, typename T2>
|
// template <typename T1, typename T2>
|
||||||
// template <typename T>
|
// template <typename T>
|
||||||
// C<T1,T2>::C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
// C<T1,T2>::C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
||||||
public void testExternalTemplateContructorOfTemplateClassHandling() {
|
public void testExternalTemplateConstructorOfTemplateClassHandling() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(11);
|
checkErrorLines(11);
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ public class ReturnCheckerTest extends CheckerTestCase {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
public void testContructorRetValue() {
|
public void testConstructorRetValue() {
|
||||||
loadCodeAndRunCpp(getAboveComment());
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
checkErrorLine(3, ReturnChecker.RET_ERR_VALUE_ID);
|
checkErrorLine(3, ReturnChecker.RET_ERR_VALUE_ID);
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ public class ReturnCheckerTest extends CheckerTestCase {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
public void testContructor_Bug323602() {
|
public void testConstructor_Bug323602() {
|
||||||
IProblemPreference macro = getPreference(ReturnChecker.RET_NO_VALUE_ID, ReturnChecker.PARAM_IMPLICIT);
|
IProblemPreference macro = getPreference(ReturnChecker.RET_NO_VALUE_ID, ReturnChecker.PARAM_IMPLICIT);
|
||||||
macro.setValue(Boolean.TRUE);
|
macro.setValue(Boolean.TRUE);
|
||||||
loadCodeAndRunCpp(getAboveComment());
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
|
|
|
@ -86,7 +86,7 @@ ptym_open(char * pts_name)
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
strcpy(pts_name, "/dev/ptmx");
|
strcpy(pts_name, "/dev/ptmx");
|
||||||
fdm = getpt();
|
fdm = posix_openpt(O_RDWR);
|
||||||
if (fdm < 0)
|
if (fdm < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (grantpt(fdm) < 0) { /* grant access to slave */
|
if (grantpt(fdm) < 0) { /* grant access to slave */
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1941,33 +1941,34 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
||||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void f(double& a) { a += 3.14; }
|
// void f(double& a) { a += 3.14; }
|
||||||
// // ...
|
// void foo1() {
|
||||||
// int foo() {
|
// double d = 0;
|
||||||
// double d = 0;
|
// f(d);
|
||||||
// f(d);
|
// }
|
||||||
// int v[20];
|
//
|
||||||
// // ...
|
// int v[20];
|
||||||
// int& g(int i) { return v[i]; }
|
// int& g(int i) { return v[i]; }
|
||||||
// // ...
|
// void foo2() {
|
||||||
// g(3) = 7;
|
// g(3) = 7;
|
||||||
// }
|
// }
|
||||||
// struct link {
|
//
|
||||||
// link* next;
|
// struct link {
|
||||||
// };
|
// link* next;
|
||||||
// link* first;
|
// };
|
||||||
// void h(link*& p) // p is a reference to pointer
|
// link* first;
|
||||||
// {
|
// void h(link*& p) // p is a reference to pointer
|
||||||
// p->next = first;
|
// {
|
||||||
// first = p;
|
// p->next = first;
|
||||||
// p = 0;
|
// first = p;
|
||||||
// }
|
// p = 0;
|
||||||
// void k()
|
// }
|
||||||
// {
|
// void k()
|
||||||
// link* q = new link;
|
// {
|
||||||
// h(q);
|
// link* q = new link;
|
||||||
// }
|
// h(q);
|
||||||
public void test8_3_2s2() throws Exception {
|
// }
|
||||||
|
public void test8_3_2s3() throws Exception {
|
||||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6392,7 +6392,25 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(6).resolveBinding());
|
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(6).resolveBinding());
|
||||||
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(8).resolveBinding());
|
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(8).resolveBinding());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <typename T> class A;
|
||||||
|
// template <template<typename> class T> class A {};
|
||||||
|
// template <template<typename> class T> class A;
|
||||||
|
// template <template<typename> class T> class B {};
|
||||||
|
// template <typename T> class B;
|
||||||
|
// template <typename T> class B {};
|
||||||
|
public void testInvalidClassRedeclaration_364226() throws Exception {
|
||||||
|
final String code = getAboveComment();
|
||||||
|
IASTTranslationUnit tu= parse(code, ParserLanguage.CPP, true, false);
|
||||||
|
CPPNameCollector nc= new CPPNameCollector();
|
||||||
|
tu.accept(nc);
|
||||||
|
assertProblemBindings(nc, 4);
|
||||||
|
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(4).resolveBinding());
|
||||||
|
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(7).resolveBinding());
|
||||||
|
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(12).resolveBinding());
|
||||||
|
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(14).resolveBinding());
|
||||||
|
}
|
||||||
|
|
||||||
// struct Foo {
|
// struct Foo {
|
||||||
// void foo();
|
// void foo();
|
||||||
// };
|
// };
|
||||||
|
|
|
@ -5583,4 +5583,59 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
public void testDirectlyNestedAmbiguity_362976() throws Exception {
|
public void testDirectlyNestedAmbiguity_362976() throws Exception {
|
||||||
parseAndCheckBindings();
|
parseAndCheckBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template<typename T, T p1, T p2, T p3=T(), T p4=T(), T p5=T(),
|
||||||
|
// T p6=T(), T p7=T(), T p8=T(), T p9=T(), T p10=T(),
|
||||||
|
// T p11=T(), T p12=T(), T p13=T(), T p14=T(), T p15=T(),
|
||||||
|
// T p16=T(), T p17=T(), T p18=T(), T p19=T(), T p20=T()
|
||||||
|
// >
|
||||||
|
// struct MaxOfN {
|
||||||
|
// template<typename X, X x1, X x2> struct Max2 {
|
||||||
|
// static const X result = (x1>x2)?x1:x2;
|
||||||
|
// };
|
||||||
|
// static const T result = Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,
|
||||||
|
// (Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,(Max2<T,p1,p2>::result),
|
||||||
|
// p3>::result),p4>::result),p5>::result),p6>::result),p7>::result),p8>::result),
|
||||||
|
// p9>::result),p10>::result),p11>::result),p12>::result),p13>::result),p14>::result),
|
||||||
|
// p15>::result),p16>::result),p17>::result),p18>::result),p19>::result),p20>::result;
|
||||||
|
// };
|
||||||
|
// int main(){
|
||||||
|
// return MaxOfN<int,1,2>::result;
|
||||||
|
// }
|
||||||
|
public void testNestedTemplateAmbiguity_363609() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// void m() {}
|
||||||
|
// };
|
||||||
|
// template <class T, void (T::*m)() = &T::m> struct B {};
|
||||||
|
// void test() {
|
||||||
|
// B<A> b1;
|
||||||
|
// }
|
||||||
|
public void testDefaultArgForNonTypeTemplateParameter_363743() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<class T> struct A {
|
||||||
|
// bool b;
|
||||||
|
// };
|
||||||
|
// class B {
|
||||||
|
// };
|
||||||
|
// template<class T> T * func();
|
||||||
|
// void test1() {
|
||||||
|
// delete func<A<B>>(); // This line causes the NPE
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// template<bool> struct C {
|
||||||
|
// int* ptr;
|
||||||
|
// };
|
||||||
|
// void test2() {
|
||||||
|
// int a = 0, b = 1;
|
||||||
|
// delete C< a<b >::ptr;
|
||||||
|
// delete C< A<B>::b >::ptr;
|
||||||
|
// }
|
||||||
|
public void testTemplateAmbiguityInDeleteExpression_364225() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@ import java.io.IOException;
|
||||||
|
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ASTPrinter;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||||
import org.eclipse.cdt.internal.core.parser.ParserException;
|
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||||
|
|
||||||
|
@ -39,6 +41,13 @@ public class ClassTypeHelperTests extends AST2BaseTest {
|
||||||
return new BindingAssertionHelper(code, true);
|
return new BindingAssertionHelper(code, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// int a;
|
||||||
|
// const int& b;
|
||||||
|
public void testTemp() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ASTPrinter.print(helper.getTranslationUnit());
|
||||||
|
}
|
||||||
|
|
||||||
// struct A {
|
// struct A {
|
||||||
// A(const A& a);
|
// A(const A& a);
|
||||||
// };
|
// };
|
||||||
|
|
|
@ -278,4 +278,41 @@ public class FaultToleranceTests extends AST2BaseTest {
|
||||||
p= getDeclaration(tu, 1);
|
p= getDeclaration(tu, 1);
|
||||||
s= getDeclaration(tu, 2);
|
s= getDeclaration(tu, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TINT* f(TINT* p) {
|
||||||
|
// TINT* f1(TINT* p) {
|
||||||
|
// TINT* f2(TINT* p) {
|
||||||
|
// TINT* f3(TINT* p) {
|
||||||
|
// TINT* f4(TINT* p) {
|
||||||
|
// TINT* f5(TINT* p) {
|
||||||
|
// TINT* f6(TINT* p) {
|
||||||
|
// TINT* f7(TINT* p) {
|
||||||
|
// TINT* f8(TINT* p) {
|
||||||
|
// TINT* f9(TINT* p) {
|
||||||
|
// TINT* f10(TINT* p) {
|
||||||
|
// TINT* f11(TINT* p) {
|
||||||
|
// TINT* f12(TINT* p) {
|
||||||
|
// TINT* f13(TINT* p) {
|
||||||
|
// TINT* f14(TINT* p) {
|
||||||
|
// TINT* f15(TINT* p) {
|
||||||
|
// TINT* f16(TINT* p) {
|
||||||
|
// TINT* f17(TINT* p) {
|
||||||
|
// TINT* f18(TINT* p) {
|
||||||
|
// TINT* f19(TINT* p) {
|
||||||
|
// TINT* f20(TINT* p) {
|
||||||
|
// TINT* f21(TINT* p) {
|
||||||
|
// TINT* f22(TINT* p) {
|
||||||
|
// TINT* f23(TINT* p) {
|
||||||
|
// TINT* f24(TINT* p) {
|
||||||
|
// TINT* f25(TINT* p) {
|
||||||
|
// TINT* f26(TINT* p) {
|
||||||
|
// TINT* f27(TINT* p) {
|
||||||
|
// TINT* f28(TINT* p) {
|
||||||
|
// TINT* f29(TINT* p) {
|
||||||
|
// }
|
||||||
|
public void testPerformanceIssue_364108() throws Exception {
|
||||||
|
final String comment= getAboveComment();
|
||||||
|
parse(comment, ParserLanguage.CPP, false, false);
|
||||||
|
parse(comment, ParserLanguage.C, false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ public class GCCCompleteParseExtensionsTest extends AST2BaseTest {
|
||||||
parseGPP( writer.toString() );
|
parseGPP( writer.toString() );
|
||||||
|
|
||||||
writer = new StringWriter();
|
writer = new StringWriter();
|
||||||
writer.write( "int x = ({ int foo() { return 1; } int y = foo (); int z;\n" ); //$NON-NLS-1$
|
writer.write( "int x = ({ int foo(); int y = foo (); int z;\n" ); //$NON-NLS-1$
|
||||||
writer.write( "if (y > 0) z = y;\n" ); //$NON-NLS-1$
|
writer.write( "if (y > 0) z = y;\n" ); //$NON-NLS-1$
|
||||||
writer.write( "else z = - y;\n" );//$NON-NLS-1$
|
writer.write( "else z = - y;\n" );//$NON-NLS-1$
|
||||||
writer.write( "z; });\n" );//$NON-NLS-1$
|
writer.write( "z; });\n" );//$NON-NLS-1$
|
||||||
|
|
|
@ -287,6 +287,42 @@ public class IndexNamesTests extends BaseTestCase {
|
||||||
fIndex.releaseReadLock();
|
fIndex.releaseReadLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// virtual void foo(){}
|
||||||
|
// template<typename C> void SetCallback(C callback){}
|
||||||
|
// void InitCallback() {
|
||||||
|
// SetCallback(&A::foo); // Can be A::foo or B::foo
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// class B: public A {
|
||||||
|
// virtual void foo(){}
|
||||||
|
// };
|
||||||
|
public void testAddressOfPolymorphicMethod_Bug363731() throws Exception {
|
||||||
|
waitForIndexer();
|
||||||
|
String content= getComment();
|
||||||
|
IFile file= createFile(getProject().getProject(), "test.cpp", content);
|
||||||
|
waitUntilFileIsIndexed(file, 4000);
|
||||||
|
|
||||||
|
fIndex.acquireReadLock();
|
||||||
|
try {
|
||||||
|
IIndexFile ifile= getIndexFile(ILinkage.CPP_LINKAGE_ID, file);
|
||||||
|
IIndexName[] names= ifile.findNames(0, content.length());
|
||||||
|
int j= 0;
|
||||||
|
for (IIndexName indexName : names) {
|
||||||
|
if (indexName.isReference() && indexName.toString().equals("foo")) {
|
||||||
|
assertEquals(true, indexName.couldBePolymorphicMethodCall());
|
||||||
|
assertEquals("A", CPPVisitor.getQualifiedName(fIndex.findBinding(indexName))[0]);
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
assertEquals(false, indexName.couldBePolymorphicMethodCall());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertEquals(1, j);
|
||||||
|
} finally {
|
||||||
|
fIndex.releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// int _i, ri, wi, rwi;
|
// int _i, ri, wi, rwi;
|
||||||
// int* rp; int* wp; int* rwp;
|
// int* rp; int* wp; int* rwp;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast;
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
@ -17,11 +17,10 @@ package org.eclipse.cdt.core.dom.ast;
|
||||||
* @noimplement This interface is not intended to be implemented by clients.
|
* @noimplement This interface is not intended to be implemented by clients.
|
||||||
*/
|
*/
|
||||||
public interface IASTDeclarator extends IASTNode, IASTNameOwner {
|
public interface IASTDeclarator extends IASTNode, IASTNameOwner {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant - empty declarator array
|
* Constant - empty declarator array
|
||||||
*/
|
*/
|
||||||
public static final IASTDeclarator[] EMPTY_DECLARATOR_ARRAY = new IASTDeclarator[0];
|
public static final IASTDeclarator[] EMPTY_DECLARATOR_ARRAY = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>POINTER_OPERATOR</code> represents the relationship between an
|
* <code>POINTER_OPERATOR</code> represents the relationship between an
|
||||||
|
@ -111,10 +110,12 @@ public interface IASTDeclarator extends IASTNode, IASTNameOwner {
|
||||||
/**
|
/**
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public IASTDeclarator copy();
|
public IASTDeclarator copy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public IASTDeclarator copy(CopyStyle style);
|
public IASTDeclarator copy(CopyStyle style);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast;
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
@ -15,19 +15,20 @@ package org.eclipse.cdt.core.dom.ast;
|
||||||
* @noimplement This interface is not intended to be implemented by clients.
|
* @noimplement This interface is not intended to be implemented by clients.
|
||||||
*/
|
*/
|
||||||
public interface IASTPointerOperator extends IASTNode {
|
public interface IASTPointerOperator extends IASTNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant/sentinel.
|
* Constant/sentinel.
|
||||||
*/
|
*/
|
||||||
public static final IASTPointerOperator[] EMPTY_ARRAY = new IASTPointerOperator[0];
|
public static final IASTPointerOperator[] EMPTY_ARRAY = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public IASTPointerOperator copy();
|
public IASTPointerOperator copy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public IASTPointerOperator copy(CopyStyle style);
|
public IASTPointerOperator copy(CopyStyle style);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast.cpp;
|
package org.eclipse.cdt.core.dom.ast.cpp;
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
||||||
* @noimplement This interface is not intended to be implemented by clients.
|
* @noimplement This interface is not intended to be implemented by clients.
|
||||||
*/
|
*/
|
||||||
public interface ICPPASTReferenceOperator extends IASTPointerOperator {
|
public interface ICPPASTReferenceOperator extends IASTPointerOperator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the operator denotes a rvalue reference (e.g. <code>int &&</code>).
|
* Returns whether the operator denotes a rvalue reference (e.g. <code>int &&</code>).
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
|
@ -30,10 +29,12 @@ public interface ICPPASTReferenceOperator extends IASTPointerOperator {
|
||||||
/**
|
/**
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public ICPPASTReferenceOperator copy();
|
public ICPPASTReferenceOperator copy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public ICPPASTReferenceOperator copy(CopyStyle style);
|
public ICPPASTReferenceOperator copy(CopyStyle style);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,9 @@ public class TypeHelper {
|
||||||
}
|
}
|
||||||
SizeofCalculator calc = ((ASTTranslationUnit) ast).getSizeofCalculator();
|
SizeofCalculator calc = ((ASTTranslationUnit) ast).getSizeofCalculator();
|
||||||
SizeAndAlignment sizeofPointer = calc.sizeAndAlignmentOfPointer();
|
SizeAndAlignment sizeofPointer = calc.sizeAndAlignmentOfPointer();
|
||||||
if (sizeofPointer == null)
|
long maxSize = sizeofPointer != null ? sizeofPointer.size : 4;
|
||||||
return true;
|
|
||||||
SizeAndAlignment sizeofType = calc.sizeAndAlignment(type);
|
SizeAndAlignment sizeofType = calc.sizeAndAlignment(type);
|
||||||
if (sizeofType == null || sizeofType.size > sizeofPointer.size)
|
if (sizeofType == null || sizeofType.size > maxSize)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -90,6 +90,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
public interface ITemplateIdStrategy {
|
public interface ITemplateIdStrategy {
|
||||||
|
boolean shallParseAsTemplateID(IASTName name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class FoundAggregateInitializer extends Exception {
|
protected static class FoundAggregateInitializer extends Exception {
|
||||||
|
@ -243,7 +244,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
throw backtrack;
|
throw backtrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTCompletionNode getCompletionNode() {
|
@Override
|
||||||
|
public IASTCompletionNode getCompletionNode() {
|
||||||
return completionNode;
|
return completionNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +557,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
parsePassed = false;
|
parsePassed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void cancel() {
|
@Override
|
||||||
|
public synchronized void cancel() {
|
||||||
isCancelled = true;
|
isCancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +645,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
throwBacktrack(n.getOffset(), n.getLength());
|
throwBacktrack(n.getOffset(), n.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTTranslationUnit parse() {
|
@Override
|
||||||
|
public IASTTranslationUnit parse() {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
translationUnit();
|
translationUnit();
|
||||||
log.traceLog("Parse " //$NON-NLS-1$
|
log.traceLog("Parse " //$NON-NLS-1$
|
||||||
|
@ -1173,22 +1177,27 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return fUnaryOperatorOffset;
|
return fUnaryOperatorOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IASTExpression copy() {
|
public IASTExpression copy() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IASTExpression copy(CopyStyle style) {
|
public IASTExpression copy(CopyStyle style) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isLValue() {
|
public boolean isLValue() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ValueCategory getValueCategory() {
|
public ValueCategory getValueCategory() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
@ -1198,11 +1207,14 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
if (LT(1) == IToken.tLPAREN) {
|
if (LT(1) == IToken.tLPAREN) {
|
||||||
final IToken mark= mark();
|
final IToken mark= mark();
|
||||||
final int startingOffset= mark.getOffset();
|
final int startingOffset= mark.getOffset();
|
||||||
|
final boolean canBeCast= canBeCastExpression();
|
||||||
consume();
|
consume();
|
||||||
IASTTypeId typeId= null;
|
IASTTypeId typeId= null;
|
||||||
try {
|
if (canBeCast) {
|
||||||
typeId= typeId(DeclarationOptions.TYPEID);
|
try {
|
||||||
} catch (BacktrackException e) {
|
typeId= typeId(DeclarationOptions.TYPEID);
|
||||||
|
} catch (BacktrackException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
||||||
consume();
|
consume();
|
||||||
|
@ -1562,7 +1574,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return skipProblemConditionInParenthesis(mark.getOffset());
|
return skipProblemConditionInParenthesis(mark.getOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean encounteredError() {
|
@Override
|
||||||
|
public boolean encounteredError() {
|
||||||
return !parsePassed;
|
return !parsePassed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1862,9 +1875,11 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
ds = nodeFactory.newDeclarationStatement(d);
|
ds = nodeFactory.newDeclarationStatement(d);
|
||||||
setRange(ds, d);
|
setRange(ds, d);
|
||||||
} catch (BacktrackException b) {
|
} catch (BacktrackException b) {
|
||||||
if (expressionStatement == null) {
|
IASTNode node = b.getNodeBeforeProblem();
|
||||||
IASTNode node = b.getNodeBeforeProblem();
|
final boolean isProblemDecl = node instanceof IASTDeclaration;
|
||||||
if (node instanceof IASTDeclaration) {
|
if (expressionStatement == null
|
||||||
|
|| (!foundSemicolon && isProblemDecl && node.contains(expressionStatement))) {
|
||||||
|
if (isProblemDecl) {
|
||||||
ds= nodeFactory.newDeclarationStatement((IASTDeclaration) node);
|
ds= nodeFactory.newDeclarationStatement((IASTDeclaration) node);
|
||||||
b.initialize(b.getProblem(), setRange(ds, node));
|
b.initialize(b.getProblem(), setRange(ds, node));
|
||||||
}
|
}
|
||||||
|
@ -2399,7 +2414,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
if (token.getType() == IGCCToken.t__declspec) {
|
if (token.getType() == IGCCToken.t__declspec) {
|
||||||
consume();
|
consume();
|
||||||
if (LT(1) == IToken.tLPAREN) {
|
if (LT(1) == IToken.tLPAREN) {
|
||||||
skipBrackets(IToken.tLPAREN, IToken.tRPAREN);
|
skipBrackets(IToken.tLPAREN, IToken.tRPAREN, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2433,24 +2448,68 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected boolean canBeCompoundLiteral() throws EndOfFileException {
|
||||||
* In case a cast expression is followed by +/- or & we should avoid it:
|
IToken m= mark();
|
||||||
* (a)+1 vs. (int)+1;
|
try {
|
||||||
* @since 4.0
|
// The parenthesis cannot be followed by a binary operator
|
||||||
*/
|
skipBrackets(IToken.tLPAREN, IToken.tRPAREN, IToken.tSEMI);
|
||||||
protected boolean avoidCastExpressionByHeuristics() throws EndOfFileException {
|
return LTcatchEOF(1) == IToken.tLBRACE;
|
||||||
if (LT(1) == IToken.tIDENTIFIER) {
|
} catch (BacktrackException bt) {
|
||||||
if (LT(2) == IToken.tRPAREN) {
|
return false;
|
||||||
switch (LT(3)) {
|
} finally {
|
||||||
case IToken.tPLUS:
|
backup(m);
|
||||||
case IToken.tMINUS:
|
}
|
||||||
case IToken.tAMPER:
|
}
|
||||||
case IToken.tSTAR:
|
|
||||||
return true;
|
protected boolean canBeCastExpression() throws EndOfFileException {
|
||||||
}
|
IToken m= mark();
|
||||||
}
|
try {
|
||||||
|
// The parenthesis cannot be followed by a binary operator
|
||||||
|
skipBrackets(IToken.tLPAREN, IToken.tRPAREN, IToken.tSEMI);
|
||||||
|
switch (LTcatchEOF(1)) {
|
||||||
|
case IToken.tAMPERASSIGN:
|
||||||
|
case IToken.tAND:
|
||||||
|
case IToken.tARROW:
|
||||||
|
case IToken.tARROWSTAR:
|
||||||
|
case IToken.tASSIGN:
|
||||||
|
case IToken.tBITOR:
|
||||||
|
case IToken.tBITORASSIGN:
|
||||||
|
case IToken.tCOLON:
|
||||||
|
case IToken.tCOMMA:
|
||||||
|
case IToken.tDIV:
|
||||||
|
case IToken.tDIVASSIGN:
|
||||||
|
case IToken.tDOT:
|
||||||
|
case IToken.tDOTSTAR:
|
||||||
|
case IToken.tEQUAL:
|
||||||
|
case IToken.tGT:
|
||||||
|
case IToken.tGT_in_SHIFTR:
|
||||||
|
case IToken.tGTEQUAL:
|
||||||
|
case IToken.tLBRACKET:
|
||||||
|
case IToken.tLTEQUAL:
|
||||||
|
case IToken.tMINUSASSIGN:
|
||||||
|
case IToken.tMOD:
|
||||||
|
case IToken.tMODASSIGN:
|
||||||
|
case IToken.tNOTEQUAL:
|
||||||
|
case IToken.tOR:
|
||||||
|
case IToken.tPLUSASSIGN:
|
||||||
|
case IToken.tQUESTION:
|
||||||
|
case IToken.tRBRACE:
|
||||||
|
case IToken.tRBRACKET:
|
||||||
|
case IToken.tRPAREN:
|
||||||
|
case IToken.tSEMI:
|
||||||
|
case IToken.tSHIFTL:
|
||||||
|
case IToken.tSHIFTLASSIGN:
|
||||||
|
case IToken.tSHIFTR:
|
||||||
|
case IToken.tSHIFTRASSIGN:
|
||||||
|
case IToken.tSTARASSIGN:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (BacktrackException bt) {
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
backup(m);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canBeTypeSpecifier() throws EndOfFileException {
|
protected boolean canBeTypeSpecifier() throws EndOfFileException {
|
||||||
|
@ -2511,12 +2570,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void skipBrackets(int left, int right) throws EndOfFileException, BacktrackException {
|
protected void skipBrackets(int left, int right, int terminator) throws EndOfFileException, BacktrackException {
|
||||||
consume(left);
|
consume(left);
|
||||||
int nesting= 0;
|
int nesting= 0;
|
||||||
while(true) {
|
while(true) {
|
||||||
final int lt1= LT(1);
|
final int lt1= LT(1);
|
||||||
if (lt1 == IToken.tEOC)
|
if (lt1 == IToken.tEOC || lt1 == terminator)
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
consume();
|
consume();
|
||||||
|
|
|
@ -29,16 +29,17 @@ public class DeclarationOptions {
|
||||||
final public static int ALLOW_FOLLOWED_BY_BRACE= 0x1000;
|
final public static int ALLOW_FOLLOWED_BY_BRACE= 0x1000;
|
||||||
final public static int ALLOW_OPAQUE_ENUM= 0x2000;
|
final public static int ALLOW_OPAQUE_ENUM= 0x2000;
|
||||||
final public static int SINGLE_DTOR= 0x4000;
|
final public static int SINGLE_DTOR= 0x4000;
|
||||||
|
final public static int ALLOW_FUNCTION_DEFINITION= 0x8000;
|
||||||
|
|
||||||
public static final DeclarationOptions
|
public static final DeclarationOptions
|
||||||
GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_OPAQUE_ENUM),
|
GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_OPAQUE_ENUM | ALLOW_FUNCTION_DEFINITION),
|
||||||
FUNCTION_STYLE_ASM= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT),
|
FUNCTION_STYLE_ASM= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT | ALLOW_FUNCTION_DEFINITION),
|
||||||
C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT),
|
C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT),
|
||||||
CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | NO_CTOR_STYLE_INITIALIZER),
|
CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | NO_CTOR_STYLE_INITIALIZER | ALLOW_FUNCTION_DEFINITION),
|
||||||
LOCAL= new DeclarationOptions(ALLOW_OPAQUE_ENUM),
|
LOCAL= new DeclarationOptions(ALLOW_OPAQUE_ENUM),
|
||||||
PARAMETER= new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_PARAMETER_PACKS | REQUIRE_SIMPLE_NAME | NO_BRACED_INITIALIZER | NO_CTOR_STYLE_INITIALIZER),
|
PARAMETER= new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_PARAMETER_PACKS | REQUIRE_SIMPLE_NAME | NO_BRACED_INITIALIZER | NO_CTOR_STYLE_INITIALIZER),
|
||||||
TYPEID= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER),
|
TYPEID= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER),
|
||||||
TYPEID_TRAILING_RETURN_TYPE= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | ALLOW_FOLLOWED_BY_BRACE),
|
TYPEID_TRAILING_RETURN_TYPE= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | ALLOW_FOLLOWED_BY_BRACE | ALLOW_FUNCTION_DEFINITION),
|
||||||
TYPEID_NEW= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | NO_FUNCTIONS | NO_NESTED | ALLOW_FOLLOWED_BY_BRACE),
|
TYPEID_NEW= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | NO_FUNCTIONS | NO_NESTED | ALLOW_FOLLOWED_BY_BRACE),
|
||||||
TYPEID_CONVERSION= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | NO_FUNCTIONS | NO_NESTED),
|
TYPEID_CONVERSION= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | NO_FUNCTIONS | NO_NESTED),
|
||||||
EXCEPTION= new DeclarationOptions(ALLOW_ABSTRACT | NO_INITIALIZER),
|
EXCEPTION= new DeclarationOptions(ALLOW_ABSTRACT | NO_INITIALIZER),
|
||||||
|
@ -60,6 +61,7 @@ public class DeclarationOptions {
|
||||||
final public boolean fRequireSimpleName;
|
final public boolean fRequireSimpleName;
|
||||||
final public boolean fAllowOpaqueEnum;
|
final public boolean fAllowOpaqueEnum;
|
||||||
final public boolean fSingleDtor;
|
final public boolean fSingleDtor;
|
||||||
|
final public boolean fAllowFunctionDefinition;
|
||||||
|
|
||||||
public DeclarationOptions(int options) {
|
public DeclarationOptions(int options) {
|
||||||
fAllowEmptySpecifier= (options & ALLOW_EMPTY_SPECIFIER) != 0;
|
fAllowEmptySpecifier= (options & ALLOW_EMPTY_SPECIFIER) != 0;
|
||||||
|
@ -76,5 +78,6 @@ public class DeclarationOptions {
|
||||||
fCanBeFollowedByBrace= fAllowBracedInitializer || (options & ALLOW_FOLLOWED_BY_BRACE) != 0;
|
fCanBeFollowedByBrace= fAllowBracedInitializer || (options & ALLOW_FOLLOWED_BY_BRACE) != 0;
|
||||||
fAllowOpaqueEnum= (options & ALLOW_OPAQUE_ENUM) != 0;
|
fAllowOpaqueEnum= (options & ALLOW_OPAQUE_ENUM) != 0;
|
||||||
fSingleDtor= (options & SINGLE_DTOR) != 0;
|
fSingleDtor= (options & SINGLE_DTOR) != 0;
|
||||||
|
fAllowFunctionDefinition= (options & ALLOW_FUNCTION_DEFINITION) != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1754,7 +1754,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
final IToken current = LA(1);
|
final IToken current = LA(1);
|
||||||
int startingOffset = current.getOffset();
|
int startingOffset = current.getOffset();
|
||||||
if (current.getType() == IToken.tLBRACKET && supportParameterInfoBlock) {
|
if (current.getType() == IToken.tLBRACKET && supportParameterInfoBlock) {
|
||||||
skipBrackets(IToken.tLBRACKET, IToken.tRBRACKET);
|
skipBrackets(IToken.tLBRACKET, IToken.tRBRACKET, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTDeclSpecifier declSpec = null;
|
IASTDeclSpecifier declSpec = null;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* John Camelon (IBM) - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
@ -19,21 +19,23 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
* Reference operator for declarators.
|
* Reference operator for declarators.
|
||||||
*/
|
*/
|
||||||
public class CPPASTReferenceOperator extends ASTNode implements ICPPASTReferenceOperator {
|
public class CPPASTReferenceOperator extends ASTNode implements ICPPASTReferenceOperator {
|
||||||
|
|
||||||
private final boolean fIsRValue;
|
private final boolean fIsRValue;
|
||||||
|
|
||||||
public CPPASTReferenceOperator(boolean isRValueReference) {
|
public CPPASTReferenceOperator(boolean isRValueReference) {
|
||||||
fIsRValue= isRValueReference;
|
fIsRValue= isRValueReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRValueReference() {
|
public boolean isRValueReference() {
|
||||||
return fIsRValue;
|
return fIsRValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CPPASTReferenceOperator copy() {
|
public CPPASTReferenceOperator copy() {
|
||||||
return copy(CopyStyle.withoutLocations);
|
return copy(CopyStyle.withoutLocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CPPASTReferenceOperator copy(CopyStyle style) {
|
public CPPASTReferenceOperator copy(CopyStyle style) {
|
||||||
CPPASTReferenceOperator copy = new CPPASTReferenceOperator(fIsRValue);
|
CPPASTReferenceOperator copy = new CPPASTReferenceOperator(fIsRValue);
|
||||||
copy.setOffsetAndLength(this);
|
copy.setOffsetAndLength(this);
|
||||||
|
@ -47,8 +49,8 @@ public class CPPASTReferenceOperator extends ASTNode implements ICPPASTReference
|
||||||
public boolean accept(ASTVisitor action) {
|
public boolean accept(ASTVisitor action) {
|
||||||
if (action.shouldVisitPointerOperators) {
|
if (action.shouldVisitPointerOperators) {
|
||||||
switch (action.visit(this)) {
|
switch (action.visit(this)) {
|
||||||
case ASTVisitor.PROCESS_ABORT : return false;
|
case ASTVisitor.PROCESS_ABORT: return false;
|
||||||
case ASTVisitor.PROCESS_SKIP : return true;
|
case ASTVisitor.PROCESS_SKIP: return true;
|
||||||
}
|
}
|
||||||
if (action.leave(this) == ASTVisitor.PROCESS_ABORT)
|
if (action.leave(this) == ASTVisitor.PROCESS_ABORT)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IASTExpression getDefault() {
|
public IASTExpression getDefault() {
|
||||||
IASTInitializerClause def= getDefaultClause();
|
IASTInitializerClause def= getDefaultClause();
|
||||||
if (def instanceof IASTExpression) {
|
if (def instanceof IASTExpression) {
|
||||||
|
@ -59,7 +61,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
||||||
IASTNode parent = name.getParent();
|
IASTNode parent = name.getParent();
|
||||||
assert parent instanceof IASTDeclarator;
|
assert parent instanceof IASTDeclarator;
|
||||||
if (parent instanceof IASTDeclarator) {
|
if (parent instanceof IASTDeclarator) {
|
||||||
IASTDeclarator dtor = (IASTDeclarator) parent;
|
IASTDeclarator dtor = ASTQueries.findOutermostDeclarator((IASTDeclarator) parent);
|
||||||
IASTInitializer initializer = dtor.getInitializer();
|
IASTInitializer initializer = dtor.getInitializer();
|
||||||
if (initializer instanceof IASTEqualsInitializer) {
|
if (initializer instanceof IASTEqualsInitializer) {
|
||||||
return ((IASTEqualsInitializer) initializer).getInitializerClause();
|
return ((IASTEqualsInitializer) initializer).getInitializerClause();
|
||||||
|
@ -70,6 +72,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ICPPTemplateArgument getDefaultValue() {
|
public ICPPTemplateArgument getDefaultValue() {
|
||||||
IASTInitializerClause dc= getDefault();
|
IASTInitializerClause dc= getDefault();
|
||||||
IASTExpression d= null;
|
IASTExpression d= null;
|
||||||
|
@ -96,6 +99,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
||||||
return new CPPTemplateArgument(val, t);
|
return new CPPTemplateArgument(val, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IType getType() {
|
public IType getType() {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
IASTNode parent= getPrimaryDeclaration().getParent();
|
IASTNode parent= getPrimaryDeclaration().getParent();
|
||||||
|
@ -110,28 +114,36 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isParameterPack() {
|
public boolean isParameterPack() {
|
||||||
return getType() instanceof ICPPParameterPackType;
|
return getType() instanceof ICPPParameterPackType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isStatic() {
|
public boolean isStatic() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean isExtern() {
|
public boolean isExtern() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean isAuto() {
|
public boolean isAuto() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean isRegister() {
|
public boolean isRegister() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public IValue getInitialValue() {
|
public IValue getInitialValue() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean isExternC() {
|
public boolean isExternC() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean isMutable() {
|
public boolean isMutable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,11 +209,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTName qualifiedName() throws BacktrackException, EndOfFileException {
|
private IASTName qualifiedName() throws BacktrackException, EndOfFileException {
|
||||||
|
return ambiguousQualifiedName(CastExprCtx.eNotInBExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IASTName ambiguousQualifiedName(CastExprCtx ctx) throws BacktrackException, EndOfFileException {
|
||||||
TemplateIdStrategy strat= new TemplateIdStrategy();
|
TemplateIdStrategy strat= new TemplateIdStrategy();
|
||||||
IToken m= mark();
|
IToken m= mark();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
try {
|
try {
|
||||||
return qualifiedName(strat, CastExprCtx.eNotInBExpr);
|
return qualifiedName(ctx, strat);
|
||||||
} catch (BacktrackException e) {
|
} catch (BacktrackException e) {
|
||||||
if (strat.setNextAlternative()) {
|
if (strat.setNextAlternative()) {
|
||||||
backup(m);
|
backup(m);
|
||||||
|
@ -223,12 +227,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a qualified name.
|
* Parses a qualified name.
|
||||||
*/
|
*/
|
||||||
private IASTName qualifiedName(ITemplateIdStrategy s, CastExprCtx ctx) throws BacktrackException, EndOfFileException {
|
private IASTName qualifiedName(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException {
|
||||||
final TemplateIdStrategy strat= (TemplateIdStrategy) s;
|
if (strat == null)
|
||||||
|
return ambiguousQualifiedName(ctx);
|
||||||
|
|
||||||
ICPPASTQualifiedName qname= null;
|
ICPPASTQualifiedName qname= null;
|
||||||
IASTName name= null;
|
IASTName name= null;
|
||||||
final int offset= LA(1).getOffset();
|
final int offset= LA(1).getOffset();
|
||||||
|
@ -288,11 +294,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (haveArgs == -1) {
|
if (haveArgs == -1) {
|
||||||
templateID= false;
|
templateID= false;
|
||||||
} else if (haveArgs == 0) {
|
} else if (haveArgs == 0) {
|
||||||
if (strat.ignoreTemplateID()) {
|
templateID= strat.shallParseAsTemplateID(name);
|
||||||
templateID= false;
|
|
||||||
} else {
|
|
||||||
strat.addTemplateName(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (templateID) {
|
if (templateID) {
|
||||||
|
@ -350,7 +352,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTName addTemplateArguments(IASTName templateName, TemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
private IASTName addTemplateArguments(IASTName templateName, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
// Parse for template arguments
|
// Parse for template arguments
|
||||||
consume(IToken.tLT);
|
consume(IToken.tLT);
|
||||||
List<IASTNode> list = templateArgumentList(strat);
|
List<IASTNode> list = templateArgumentList(strat);
|
||||||
|
@ -566,7 +568,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IASTNode> templateArgumentList(TemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
private List<IASTNode> templateArgumentList(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
int startingOffset = LA(1).getOffset();
|
int startingOffset = LA(1).getOffset();
|
||||||
int endOffset = 0;
|
int endOffset = 0;
|
||||||
List<IASTNode> list= null;
|
List<IASTNode> list= null;
|
||||||
|
@ -596,7 +598,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTNode templateArgument(TemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
private IASTNode templateArgument(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
IToken argStart = mark();
|
IToken argStart = mark();
|
||||||
ICPPASTTypeId typeId= null;
|
ICPPASTTypeId typeId= null;
|
||||||
int lt1= 0;
|
int lt1= 0;
|
||||||
|
@ -742,7 +744,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return expression(ExprKind.eConstant, BinaryExprCtx.eNotInTemplateID, null, null);
|
return expression(ExprKind.eConstant, BinaryExprCtx.eNotInTemplateID, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx, IASTInitializerClause expr, TemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx, IASTInitializerClause expr, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
final boolean allowComma= kind==ExprKind.eExpression;
|
final boolean allowComma= kind==ExprKind.eExpression;
|
||||||
boolean allowAssignment= kind !=ExprKind.eConstant;
|
boolean allowAssignment= kind !=ExprKind.eConstant;
|
||||||
|
|
||||||
|
@ -750,12 +752,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return throwExpression();
|
return throwExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean handleVariants= strat == null;
|
|
||||||
if (handleVariants) {
|
|
||||||
strat= new TemplateIdStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final int startOffset= expr != null ? ((ASTNode) expr).getOffset() : LA(1).getOffset();
|
final int startOffset= expr != null ? ((ASTNode) expr).getOffset() : LA(1).getOffset();
|
||||||
int lt1;
|
int lt1;
|
||||||
int conditionCount= 0;
|
int conditionCount= 0;
|
||||||
|
@ -763,7 +759,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
NameOrTemplateIDVariants variants= null;
|
NameOrTemplateIDVariants variants= null;
|
||||||
|
|
||||||
if (expr == null) {
|
if (expr == null) {
|
||||||
Object e = castExpressionForBinaryExpression(handleVariants, strat);
|
Object e = castExpressionForBinaryExpression(strat);
|
||||||
if (e instanceof IASTExpression) {
|
if (e instanceof IASTExpression) {
|
||||||
expr= (IASTExpression) e;
|
expr= (IASTExpression) e;
|
||||||
} else {
|
} else {
|
||||||
|
@ -934,7 +930,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
// Cast expression
|
// Cast expression
|
||||||
IToken m= mark();
|
IToken m= mark();
|
||||||
try {
|
try {
|
||||||
Object e = castExpressionForBinaryExpression(handleVariants, strat);
|
Object e = castExpressionForBinaryExpression(strat);
|
||||||
if (e instanceof IASTExpression) {
|
if (e instanceof IASTExpression) {
|
||||||
expr= (IASTExpression) e;
|
expr= (IASTExpression) e;
|
||||||
} else {
|
} else {
|
||||||
|
@ -999,18 +995,19 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return buildExpression(lastOperator, expr);
|
return buildExpression(lastOperator, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object castExpressionForBinaryExpression(boolean handleVariants, final TemplateIdStrategy strat)
|
public Object castExpressionForBinaryExpression(ITemplateIdStrategy s)
|
||||||
throws EndOfFileException, BacktrackException {
|
throws EndOfFileException, BacktrackException {
|
||||||
if (!handleVariants)
|
if (s != null) {
|
||||||
return castExpression(CastExprCtx.eDirectlyInBExpr, strat);
|
return castExpression(CastExprCtx.eDirectlyInBExpr, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateIdStrategy strat= new TemplateIdStrategy();
|
||||||
Variant variants= null;
|
Variant variants= null;
|
||||||
IASTExpression singleExpression= null;
|
IASTExpression singleExpression= null;
|
||||||
IASTName[] firstNames= null;
|
IASTName[] firstNames= null;
|
||||||
|
|
||||||
final IToken mark= mark();
|
final IToken mark= mark();
|
||||||
IToken lastToken= null;
|
IToken lastToken= null;
|
||||||
strat.reset();
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
try {
|
try {
|
||||||
IASTExpression e = castExpression(CastExprCtx.eDirectlyInBExpr, strat);
|
IASTExpression e = castExpression(CastExprCtx.eDirectlyInBExpr, strat);
|
||||||
|
@ -1454,14 +1451,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
// ( type-name ) { initializer-list , }
|
// ( type-name ) { initializer-list , }
|
||||||
IToken m = mark();
|
IToken m = mark();
|
||||||
try {
|
try {
|
||||||
int offset = consume().getOffset();
|
if (canBeCompoundLiteral()) {
|
||||||
IASTTypeId t= typeId(DeclarationOptions.TYPEID);
|
int offset = consume().getOffset();
|
||||||
consume(IToken.tRPAREN);
|
IASTTypeId t= typeId(DeclarationOptions.TYPEID);
|
||||||
if (LT(1) == IToken.tLBRACE) {
|
consume(IToken.tRPAREN);
|
||||||
IASTInitializer i = bracedInitList(false);
|
if (LT(1) == IToken.tLBRACE) {
|
||||||
firstExpression= nodeFactory.newTypeIdInitializerExpression(t, i);
|
IASTInitializer i = bracedInitList(false);
|
||||||
setRange(firstExpression, offset, calculateEndOffset(i));
|
firstExpression= nodeFactory.newTypeIdInitializerExpression(t, i);
|
||||||
break;
|
setRange(firstExpression, offset, calculateEndOffset(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
}
|
}
|
||||||
|
@ -1554,7 +1553,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
isTemplate = true;
|
isTemplate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTName name = qualifiedName(strat, ctx);
|
IASTName name = qualifiedName(ctx, strat);
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
||||||
|
@ -1577,7 +1576,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
isTemplate = true;
|
isTemplate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = qualifiedName(strat, ctx);
|
name = qualifiedName(ctx, strat);
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
||||||
|
@ -1690,7 +1689,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.t_operator:
|
case IToken.t_operator:
|
||||||
case IToken.tCOMPLETION:
|
case IToken.tCOMPLETION:
|
||||||
case IToken.tBITCOMPLEMENT: {
|
case IToken.tBITCOMPLEMENT: {
|
||||||
IASTName name = qualifiedName(strat, ctx);
|
IASTName name = qualifiedName(ctx, strat);
|
||||||
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
|
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
|
||||||
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
|
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
|
||||||
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());
|
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());
|
||||||
|
@ -2388,7 +2387,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.t_try:
|
case IToken.t_try:
|
||||||
case IToken.tLBRACE:
|
case IToken.tLBRACE:
|
||||||
case IToken.tASSIGN: // defaulted or deleted function definition
|
case IToken.tASSIGN: // defaulted or deleted function definition
|
||||||
if (declarators.length != 1)
|
if (declarators.length != 1 || !declOption.fAllowFunctionDefinition)
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
dtor= declarators[0];
|
dtor= declarators[0];
|
||||||
|
@ -2568,7 +2567,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
final int startOffset= LA(1).getOffset();
|
final int startOffset= LA(1).getOffset();
|
||||||
|
|
||||||
if (LT(1) == IToken.tLBRACKET && supportParameterInfoBlock) {
|
if (LT(1) == IToken.tLBRACKET && supportParameterInfoBlock) {
|
||||||
skipBrackets(IToken.tLBRACKET, IToken.tRBRACKET);
|
skipBrackets(IToken.tLBRACKET, IToken.tRBRACKET, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTDeclSpecifier declSpec= null;
|
IASTDeclSpecifier declSpec= null;
|
||||||
|
|
|
@ -14,6 +14,8 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.ITemplateIdStrategy;
|
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.ITemplateIdStrategy;
|
||||||
|
|
||||||
|
@ -27,50 +29,52 @@ final class TemplateIdStrategy implements ITemplateIdStrategy {
|
||||||
private IASTName[] fTemplateNames;
|
private IASTName[] fTemplateNames;
|
||||||
|
|
||||||
public TemplateIdStrategy() {
|
public TemplateIdStrategy() {
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
fCurrentBranchPoint= -1;
|
fCurrentBranchPoint= -1;
|
||||||
fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
|
fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
|
||||||
if (fSimpleIDs != null) {
|
|
||||||
fSimpleIDs.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean ignoreTemplateID() {
|
@Override
|
||||||
|
public boolean shallParseAsTemplateID(IASTName name) {
|
||||||
fCurrentBranchPoint++;
|
fCurrentBranchPoint++;
|
||||||
return fSimpleIDs == null ? false : fSimpleIDs.get(fCurrentBranchPoint);
|
|
||||||
}
|
boolean templateID= fSimpleIDs == null || !fSimpleIDs.get(fCurrentBranchPoint);
|
||||||
|
if (templateID) {
|
||||||
public void addTemplateName(IASTName name) {
|
fTemplateNames= ArrayUtil.append(fTemplateNames, name);
|
||||||
fTemplateNames= ArrayUtil.append(fTemplateNames, name);
|
}
|
||||||
|
return templateID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setNextAlternative() {
|
public boolean setNextAlternative() {
|
||||||
final int bp = fCurrentBranchPoint;
|
int bp = fCurrentBranchPoint;
|
||||||
if (bp < 0)
|
if (bp < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
fCurrentBranchPoint= -1;
|
fCurrentBranchPoint= -1;
|
||||||
|
IASTName[] names = getTemplateNames();
|
||||||
|
int nameLen= names.length;
|
||||||
fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
|
fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
|
||||||
if (fSimpleIDs == null) {
|
if (fSimpleIDs == null) {
|
||||||
fSimpleIDs= new BitSet();
|
fSimpleIDs= new BitSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a new branch as far right as possible.
|
// Set a new branch as far right as possible.
|
||||||
final int len = fSimpleIDs.length();
|
while (bp >= 0) {
|
||||||
if (len <= bp) {
|
if (!fSimpleIDs.get(bp)) {
|
||||||
fSimpleIDs.set(bp);
|
if (nameLen == 0 || !hasMultipleArgs(names[--nameLen])) {
|
||||||
return true;
|
fSimpleIDs.clear(bp+1, Integer.MAX_VALUE);
|
||||||
}
|
fSimpleIDs.set(bp);
|
||||||
|
return true;
|
||||||
for (int branch= Math.min(bp, len-2); branch>=0; branch--) {
|
}
|
||||||
if (!fSimpleIDs.get(branch)) {
|
|
||||||
fSimpleIDs.clear(branch+1, len);
|
|
||||||
fSimpleIDs.set(branch);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
bp--;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasMultipleArgs(IASTName templateName) {
|
||||||
|
IASTNode parent= templateName.getParent();
|
||||||
|
if (parent instanceof ICPPASTTemplateId) {
|
||||||
|
return ((ICPPASTTemplateId) parent).getTemplateArguments().length > 1;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -781,7 +781,9 @@ public class CPPSemantics {
|
||||||
data.foundItems = ArrayUtil.addAll(Object.class, (Object[]) data.foundItems, (Object[]) results);
|
data.foundItems = ArrayUtil.addAll(Object.class, (Object[]) data.foundItems, (Object[]) results);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data.foundItems = mergePrefixResults((CharArrayObjectMap) data.foundItems, results, scoped);
|
@SuppressWarnings("unchecked")
|
||||||
|
final CharArrayObjectMap<Object> oldItems = (CharArrayObjectMap<Object>) data.foundItems;
|
||||||
|
data.foundItems = mergePrefixResults(oldItems, results, scoped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,15 +793,17 @@ public class CPPSemantics {
|
||||||
* @param scoped
|
* @param scoped
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static CharArrayObjectMap mergePrefixResults(CharArrayObjectMap dest, Object source, boolean scoped) {
|
static CharArrayObjectMap<Object> mergePrefixResults(CharArrayObjectMap<Object> dest, Object source, boolean scoped) {
|
||||||
if (source == null) return dest;
|
if (source == null) return dest;
|
||||||
CharArrayObjectMap resultMap = (dest != null) ? dest : new CharArrayObjectMap(2);
|
CharArrayObjectMap<Object> resultMap = (dest != null) ? dest : new CharArrayObjectMap<Object>(2);
|
||||||
|
|
||||||
CharArrayObjectMap map = null;
|
CharArrayObjectMap<Object> map = null;
|
||||||
Object[] objs = null;
|
Object[] objs = null;
|
||||||
int size;
|
int size;
|
||||||
if (source instanceof CharArrayObjectMap) {
|
if (source instanceof CharArrayObjectMap) {
|
||||||
map = (CharArrayObjectMap) source;
|
@SuppressWarnings("unchecked")
|
||||||
|
final CharArrayObjectMap<Object> sourceMap = (CharArrayObjectMap<Object>) source;
|
||||||
|
map = sourceMap;
|
||||||
size= map.size();
|
size= map.size();
|
||||||
} else {
|
} else {
|
||||||
if (source instanceof Object[])
|
if (source instanceof Object[])
|
||||||
|
@ -3499,7 +3503,7 @@ public class CPPSemantics {
|
||||||
LookupData data = createLookupData(name);
|
LookupData data = createLookupData(name);
|
||||||
data.contentAssist = true;
|
data.contentAssist = true;
|
||||||
data.prefixLookup = prefixLookup;
|
data.prefixLookup = prefixLookup;
|
||||||
data.foundItems = new CharArrayObjectMap(2);
|
data.foundItems = new CharArrayObjectMap<Object>(2);
|
||||||
|
|
||||||
// Convert namespaces to scopes.
|
// Convert namespaces to scopes.
|
||||||
List<ICPPScope> nsScopes= new ArrayList<ICPPScope>();
|
List<ICPPScope> nsScopes= new ArrayList<ICPPScope>();
|
||||||
|
@ -3567,7 +3571,8 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
}
|
}
|
||||||
CharArrayObjectMap map = (CharArrayObjectMap) data.foundItems;
|
@SuppressWarnings("unchecked")
|
||||||
|
CharArrayObjectMap<Object> map = (CharArrayObjectMap<Object>) data.foundItems;
|
||||||
IBinding[] result = IBinding.EMPTY_BINDING_ARRAY;
|
IBinding[] result = IBinding.EMPTY_BINDING_ARRAY;
|
||||||
if (!map.isEmpty()) {
|
if (!map.isEmpty()) {
|
||||||
char[] key = null;
|
char[] key = null;
|
||||||
|
@ -3686,7 +3691,7 @@ public class CPPSemantics {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSameTemplateParameter(ICPPTemplateParameter tp1, ICPPASTTemplateParameter tp2) {
|
static boolean isSameTemplateParameter(ICPPTemplateParameter tp1, ICPPASTTemplateParameter tp2) {
|
||||||
if (tp1.isParameterPack() != tp2.isParameterPack())
|
if (tp1.isParameterPack() != tp2.isParameterPack())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -460,10 +460,9 @@ public class CPPVisitor extends ASTQueries {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boolean template = false;
|
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
|
||||||
ICPPScope scope = (ICPPScope) getContainingScope(name);
|
ICPPScope scope = (ICPPScope) getContainingScope(name);
|
||||||
while (scope instanceof ICPPTemplateScope) {
|
while (scope instanceof ICPPTemplateScope) {
|
||||||
template = true;
|
|
||||||
scope= (ICPPScope) scope.getParent();
|
scope= (ICPPScope) scope.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,35 +492,21 @@ public class CPPVisitor extends ASTQueries {
|
||||||
|
|
||||||
if (binding instanceof ICPPClassType) {
|
if (binding instanceof ICPPClassType) {
|
||||||
final ICPPInternalBinding ib = (ICPPInternalBinding) binding;
|
final ICPPInternalBinding ib = (ICPPInternalBinding) binding;
|
||||||
if ((binding instanceof ICPPClassTemplate) == template) {
|
if (templateParametersMatch((ICPPClassType) binding, templateDecl)) {
|
||||||
ib.addDeclaration(elabType);
|
ib.addDeclaration(elabType);
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
if (CPPSemantics.declaredBefore(binding, name, false)) {
|
|
||||||
|
if (CPPSemantics.declaredBefore(ib, name, false)) {
|
||||||
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
|
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
|
||||||
}
|
}
|
||||||
|
markRedeclaration(ib);
|
||||||
// Mark the other declarations as problem and create the binding
|
|
||||||
final IASTNode[] decls = ib.getDeclarations();
|
|
||||||
if (decls != null) {
|
|
||||||
for (IASTNode decl : decls) {
|
|
||||||
if (decl instanceof IASTName) {
|
|
||||||
final IASTName n = (IASTName) decl;
|
|
||||||
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDECLARATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IASTNode decl= ib.getDefinition();
|
|
||||||
if (decl instanceof IASTName) {
|
|
||||||
final IASTName n = (IASTName) decl;
|
|
||||||
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a binding
|
// Create a binding
|
||||||
if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) {
|
if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) {
|
||||||
if (template)
|
if (templateDecl != null)
|
||||||
binding = new CPPClassTemplate(name);
|
binding = new CPPClassTemplate(name);
|
||||||
else
|
else
|
||||||
binding = new CPPClassType(name, binding);
|
binding = new CPPClassType(name, binding);
|
||||||
|
@ -535,44 +520,91 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void markRedeclaration(final ICPPInternalBinding ib) {
|
||||||
|
// Mark the other declarations as problem and create the binding
|
||||||
|
final IASTNode[] decls = ib.getDeclarations();
|
||||||
|
if (decls != null) {
|
||||||
|
for (IASTNode decl : decls) {
|
||||||
|
if (decl instanceof IASTName) {
|
||||||
|
final IASTName n = (IASTName) decl;
|
||||||
|
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDECLARATION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IASTNode decl= ib.getDefinition();
|
||||||
|
if (decl instanceof IASTName) {
|
||||||
|
final IASTName n = (IASTName) decl;
|
||||||
|
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether a class binding matches the template parameters of another declaration
|
||||||
|
*/
|
||||||
|
private static boolean templateParametersMatch(ICPPClassType binding,
|
||||||
|
ICPPASTTemplateDeclaration templateDecl) {
|
||||||
|
final boolean isTemplate= binding instanceof ICPPClassTemplate;
|
||||||
|
if (templateDecl == null)
|
||||||
|
return !isTemplate;
|
||||||
|
if (!isTemplate)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ICPPTemplateParameter[] pars1 = ((ICPPClassTemplate) binding).getTemplateParameters();
|
||||||
|
ICPPASTTemplateParameter[] pars2 = templateDecl.getTemplateParameters();
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
for (ICPPASTTemplateParameter p2 : pars2) {
|
||||||
|
if (i >= pars1.length)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!CPPSemantics.isSameTemplateParameter(pars1[i++], p2))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static IBinding createBinding(ICPPASTCompositeTypeSpecifier compType) {
|
private static IBinding createBinding(ICPPASTCompositeTypeSpecifier compType) {
|
||||||
IASTName name = compType.getName();
|
IASTName name = compType.getName();
|
||||||
if (name instanceof ICPPASTQualifiedName) {
|
if (name instanceof ICPPASTQualifiedName) {
|
||||||
IASTName[] ns = ((ICPPASTQualifiedName) name).getNames();
|
IASTName[] ns = ((ICPPASTQualifiedName) name).getNames();
|
||||||
name = ns[ns.length - 1];
|
name = ns[ns.length - 1];
|
||||||
}
|
}
|
||||||
|
if (name instanceof ICPPASTTemplateId)
|
||||||
IBinding binding = null;
|
return CPPTemplates.createBinding((ICPPASTTemplateId) name);
|
||||||
|
|
||||||
ICPPScope scope = (ICPPScope) getContainingScope(name);
|
ICPPScope scope = (ICPPScope) getContainingScope(name);
|
||||||
try {
|
try {
|
||||||
boolean template = false;
|
|
||||||
while (scope instanceof ICPPTemplateScope) {
|
while (scope instanceof ICPPTemplateScope) {
|
||||||
template = true;
|
|
||||||
scope= (ICPPScope) scope.getParent();
|
scope= (ICPPScope) scope.getParent();
|
||||||
}
|
}
|
||||||
if (name instanceof ICPPASTTemplateId) {
|
|
||||||
return CPPTemplates.createBinding((ICPPASTTemplateId) name);
|
|
||||||
}
|
|
||||||
if (name.getLookupKey().length > 0 && scope != null) // can't lookup anonymous things
|
|
||||||
binding = scope.getBinding(name, false);
|
|
||||||
if (binding instanceof ICPPInternalBinding && binding instanceof ICPPClassType && name.isActive()) {
|
|
||||||
ICPPInternalBinding internal = (ICPPInternalBinding) binding;
|
|
||||||
if (internal.getDefinition() == null && (binding instanceof ICPPClassTemplate) == template) {
|
|
||||||
ASTInternal.addDefinition(internal, compType);
|
|
||||||
} else {
|
|
||||||
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (template) {
|
|
||||||
binding = new CPPClassTemplate(name);
|
|
||||||
} else {
|
|
||||||
binding = new CPPClassType(name, binding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
binding = e.getProblem();
|
return e.getProblem();
|
||||||
}
|
}
|
||||||
return binding;
|
|
||||||
|
// Can't lookup anonymous names
|
||||||
|
IBinding binding= null;
|
||||||
|
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
|
||||||
|
if (name.getLookupKey().length > 0 && scope != null) {
|
||||||
|
binding = scope.getBinding(name, false);
|
||||||
|
|
||||||
|
if (binding instanceof ICPPInternalBinding
|
||||||
|
&& binding instanceof ICPPClassType && name.isActive()) {
|
||||||
|
ICPPInternalBinding ib = (ICPPInternalBinding) binding;
|
||||||
|
if (ib.getDefinition() == null
|
||||||
|
&& templateParametersMatch((ICPPClassType) binding, templateDecl)) {
|
||||||
|
ASTInternal.addDefinition(ib, compType);
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
if (CPPSemantics.declaredBefore(ib, name, false)) {
|
||||||
|
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION);
|
||||||
|
}
|
||||||
|
markRedeclaration(ib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (templateDecl != null)
|
||||||
|
return new CPPClassTemplate(name);
|
||||||
|
|
||||||
|
return new CPPClassType(name, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBinding createBinding(IASTDeclaration declaration) {
|
private static IBinding createBinding(IASTDeclaration declaration) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
|
@ -110,6 +111,7 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
|
||||||
return IIndexCPPBindingConstants.CPPMETHOD;
|
return IIndexCPPBindingConstants.CPPMETHOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isVirtual() {
|
public boolean isVirtual() {
|
||||||
return getBit(getAnnotation1(), PDOMCPPAnnotation.VIRTUAL_OFFSET);
|
return getBit(getAnnotation1(), PDOMCPPAnnotation.VIRTUAL_OFFSET);
|
||||||
}
|
}
|
||||||
|
@ -120,10 +122,12 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
|
||||||
return annotation1;
|
return annotation1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isPureVirtual() {
|
public boolean isPureVirtual() {
|
||||||
return getBit(getAnnotation1(), PDOMCPPAnnotation.PURE_VIRTUAL_OFFSET);
|
return getBit(getAnnotation1(), PDOMCPPAnnotation.PURE_VIRTUAL_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isDestructor() {
|
public boolean isDestructor() {
|
||||||
return getBit(getAnnotation1(), PDOMCPPAnnotation.DESTRUCTOR_OFFSET);
|
return getBit(getAnnotation1(), PDOMCPPAnnotation.DESTRUCTOR_OFFSET);
|
||||||
}
|
}
|
||||||
|
@ -133,10 +137,12 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isImplicit() {
|
public boolean isImplicit() {
|
||||||
return getBit(getAnnotation1(), PDOMCPPAnnotation.IMPLICIT_METHOD_OFFSET);
|
return getBit(getAnnotation1(), PDOMCPPAnnotation.IMPLICIT_METHOD_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isExplicit() {
|
public boolean isExplicit() {
|
||||||
return getBit(getAnnotation1(), PDOMCPPAnnotation.EXPLICIT_METHOD_OFFSET);
|
return getBit(getAnnotation1(), PDOMCPPAnnotation.EXPLICIT_METHOD_OFFSET);
|
||||||
}
|
}
|
||||||
|
@ -169,10 +175,12 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getVisibility() {
|
public int getVisibility() {
|
||||||
return PDOMCPPAnnotation.getVisibility(getAnnotation());
|
return PDOMCPPAnnotation.getVisibility(getAnnotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ICPPClassType getClassOwner() {
|
public ICPPClassType getClassOwner() {
|
||||||
return (ICPPClassType) getOwner();
|
return (ICPPClassType) getOwner();
|
||||||
}
|
}
|
||||||
|
@ -194,8 +202,19 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
|
||||||
public int getAdditionalNameFlags(int standardFlags, IASTName name) {
|
public int getAdditionalNameFlags(int standardFlags, IASTName name) {
|
||||||
if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) {
|
if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) {
|
||||||
IASTNode parent= name.getParent();
|
IASTNode parent= name.getParent();
|
||||||
if (parent instanceof ICPPASTFieldReference) {
|
if (parent instanceof ICPPASTQualifiedName) {
|
||||||
// the name is not qualified
|
// When taking the address of a method it will be called without suppressing
|
||||||
|
// the virtual mechanism
|
||||||
|
parent= parent.getParent();
|
||||||
|
if (parent instanceof IASTIdExpression) {
|
||||||
|
parent= parent.getParent();
|
||||||
|
if (parent instanceof IASTUnaryExpression) {
|
||||||
|
if (((IASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_amper)
|
||||||
|
return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parent instanceof ICPPASTFieldReference) {
|
||||||
|
// The name is not qualified
|
||||||
ICPPASTFieldReference fr= (ICPPASTFieldReference) parent;
|
ICPPASTFieldReference fr= (ICPPASTFieldReference) parent;
|
||||||
parent= parent.getParent();
|
parent= parent.getParent();
|
||||||
if (parent instanceof IASTFunctionCallExpression) {
|
if (parent instanceof IASTFunctionCallExpression) {
|
||||||
|
@ -221,9 +240,8 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
|
||||||
return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL;
|
return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (parent instanceof IASTIdExpression) {
|
||||||
// calling a member from within a member
|
// Calling a member from within a member
|
||||||
else if (parent instanceof IASTIdExpression) {
|
|
||||||
if (parent.getParent() instanceof IASTFunctionCallExpression) {
|
if (parent.getParent() instanceof IASTFunctionCallExpression) {
|
||||||
return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL;
|
return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
@ -70,7 +70,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//!Generate Getters and Setters One Getter Selection with Namespace
|
//!Generate Getters and Setters One Getter Selection with Namespace
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
//@.config
|
//@.config
|
||||||
|
@ -132,7 +132,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
|
@ -177,7 +177,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//!Generate Getters and Setters One Setter Selection
|
//!Generate Getters and Setters One Setter Selection
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
|
@ -240,7 +240,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
@ -281,7 +281,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//!Generate Getters and Setters Getter and Setter Selection
|
//!Generate Getters and Setters Getter and Setter Selection
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
//@.config
|
//@.config
|
||||||
|
@ -343,7 +343,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -367,7 +367,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
@ -384,7 +384,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -416,7 +416,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//!Generate Getters and Setters Multiple Selection
|
//!Generate Getters and Setters Multiple Selection
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
//@.config
|
//@.config
|
||||||
|
@ -450,7 +450,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -465,7 +465,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
|
@ -499,7 +499,7 @@ public:
|
||||||
this->systemId = systemId;
|
this->systemId = systemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -514,7 +514,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//!Generate Getters and Setters Visibility order 1
|
//!Generate Getters and Setters Visibility order 1
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
|
@ -596,7 +596,7 @@ private:
|
||||||
int /*$*/id/*$$*/;
|
int /*$*/id/*$$*/;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
|
@ -616,7 +616,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//!Generate Getters and Setters no Methods
|
//!Generate Getters and Setters no Methods
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
|
@ -704,53 +704,37 @@ class test {
|
||||||
|
|
||||||
#endif /* TEST_H_ */
|
#endif /* TEST_H_ */
|
||||||
|
|
||||||
//!Generate Getters and Setters One Getter Selection Separate Definition
|
//!Generate Getters and Setters, Pass by Reference, Separate Definition
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
//@.config
|
//@.config
|
||||||
filename=C.h
|
filename=C.h
|
||||||
getters=name
|
getters=name
|
||||||
|
setters=name
|
||||||
definitionSeparate=true
|
definitionSeparate=true
|
||||||
//@C.cpp
|
|
||||||
#include "C.h"
|
|
||||||
|
|
||||||
int Person::SocSecNo() {
|
|
||||||
return socSecNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//=
|
|
||||||
#include "C.h"
|
|
||||||
|
|
||||||
char* Person::getName() const {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Person::SocSecNo() {
|
|
||||||
return socSecNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//@C.h
|
//@C.h
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
|
||||||
|
struct FullName {
|
||||||
|
const char* first;
|
||||||
|
const char* last;
|
||||||
|
FullName(const FullName& other);
|
||||||
|
~FullName();
|
||||||
|
};
|
||||||
|
|
||||||
class Person {
|
class Person {
|
||||||
private:
|
private:
|
||||||
int systemId;
|
int systemId;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char* name;
|
FullName name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const int socSecNo;
|
const int socSecNo;
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -769,25 +753,33 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
|
||||||
|
struct FullName {
|
||||||
|
const char* first;
|
||||||
|
const char* last;
|
||||||
|
FullName(const FullName& other);
|
||||||
|
~FullName();
|
||||||
|
};
|
||||||
|
|
||||||
class Person {
|
class Person {
|
||||||
private:
|
private:
|
||||||
int systemId;
|
int systemId;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char* name;
|
FullName name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const int socSecNo;
|
const int socSecNo;
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
char* getName() const;
|
const FullName& getName() const;
|
||||||
|
void setName(const FullName& name);
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -806,7 +798,35 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
//@C.cpp
|
||||||
|
#include "C.h"
|
||||||
|
|
||||||
|
int Person::SocSecNo() {
|
||||||
|
return socSecNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//=
|
||||||
|
#include "C.h"
|
||||||
|
|
||||||
|
const FullName& Person::getName() const {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Person::setName(const FullName& name) {
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Person::SocSecNo() {
|
||||||
|
return socSecNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
}
|
||||||
|
|
||||||
//!Generate Getters and Setters One Getter Selection with Namespace Separate Definition
|
//!Generate Getters and Setters One Getter Selection with Namespace Separate Definition
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
//@.config
|
//@.config
|
||||||
|
@ -863,7 +883,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -888,7 +908,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
|
@ -908,7 +928,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -934,7 +954,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//!Generate Getters and Setters One Setter Selection Separate Definition
|
//!Generate Getters and Setters One Setter Selection Separate Definition
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
|
@ -984,7 +1004,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -1008,7 +1028,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
@ -1025,7 +1045,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -1050,7 +1070,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
//!Getter and Setter Selection Separate Definition
|
//!Getter and Setter Selection Separate Definition
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
//@.config
|
//@.config
|
||||||
|
@ -1102,7 +1122,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -1126,7 +1146,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
|
@ -1144,7 +1164,7 @@ public:
|
||||||
|
|
||||||
Person myFriend;
|
Person myFriend;
|
||||||
|
|
||||||
Person(int socSecNo); // contructor
|
Person(int socSecNo); // constructor
|
||||||
|
|
||||||
~Person(); // destructor
|
~Person(); // destructor
|
||||||
|
|
||||||
|
@ -1170,7 +1190,7 @@ public:
|
||||||
|
|
||||||
int gooo = 1;
|
int gooo = 1;
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//!Generate Getters and Setters no Methods Separate Definition
|
//!Generate Getters and Setters no Methods Separate Definition
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
|
@ -1188,7 +1208,7 @@ private:
|
||||||
int /*$*/id/*$$*/;
|
int /*$*/id/*$$*/;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
|
@ -1212,7 +1232,7 @@ inline void Person::setId(int id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /*C_H_*/
|
#endif /* C_H_ */
|
||||||
|
|
||||||
//!No Methods Separate Definition
|
//!No Methods Separate Definition
|
||||||
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
|
||||||
|
|
|
@ -130,7 +130,7 @@ public class CHQueries {
|
||||||
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
|
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
|
||||||
while (true) {
|
while (true) {
|
||||||
ICElement[] defs= null;
|
ICElement[] defs= null;
|
||||||
if (binding instanceof ICPPMethod) {
|
if (binding instanceof ICPPMethod && name.couldBePolymorphicMethodCall()) {
|
||||||
defs = findOverriders(index, (ICPPMethod) binding);
|
defs = findOverriders(index, (ICPPMethod) binding);
|
||||||
}
|
}
|
||||||
if (defs == null) {
|
if (defs == null) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Institute for Software - initial API and implementation
|
* Institute for Software - initial API and implementation
|
||||||
|
@ -24,7 +24,9 @@ import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||||
|
import org.eclipse.cdt.core.dom.rewrite.TypeHelper;
|
||||||
import org.eclipse.cdt.core.parser.Keywords;
|
import org.eclipse.cdt.core.parser.Keywords;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression;
|
||||||
|
@ -37,28 +39,39 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTParameterDeclaration;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTParameterDeclaration;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReferenceOperator;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReturnStatement;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReturnStatement;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclSpecifier;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclSpecifier;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
|
|
||||||
public class FunctionFactory {
|
public class GetterSetterFactory {
|
||||||
|
private final IASTName fieldName;
|
||||||
|
private final IASTSimpleDeclaration fieldDeclaration;
|
||||||
|
private boolean passByReference;
|
||||||
|
|
||||||
public static IASTFunctionDefinition createGetterDefinition(IASTName fieldName,
|
public GetterSetterFactory(IASTName fieldName, IASTSimpleDeclaration fieldDeclaration) {
|
||||||
IASTSimpleDeclaration fieldDeclaration, ICPPASTQualifiedName name) {
|
this.fieldName = fieldName;
|
||||||
|
this.fieldDeclaration = fieldDeclaration;
|
||||||
|
IType type = CPPVisitor.createType(fieldDeclaration.getDeclSpecifier());
|
||||||
|
passByReference = TypeHelper.shouldBePassedByReference(type, fieldDeclaration.getTranslationUnit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTFunctionDefinition createGetterDefinition(ICPPASTQualifiedName qualifiedName) {
|
||||||
IASTFunctionDefinition getter = new CPPASTFunctionDefinition();
|
IASTFunctionDefinition getter = new CPPASTFunctionDefinition();
|
||||||
|
|
||||||
getter.setDeclSpecifier(fieldDeclaration.getDeclSpecifier().copy(CopyStyle.withLocations));
|
getter.setDeclSpecifier(getParamOrReturnDeclSpecifier());
|
||||||
IASTDeclarator getterDeclarator = getGetterDeclarator(fieldName, fieldDeclaration, name);
|
IASTDeclarator getterDeclarator = getGetterDeclarator(qualifiedName);
|
||||||
// IASTFunctionDefinition. expects the outermost IASTFunctionDeclarator in declarator hierarchy
|
// IASTFunctionDefinition expects the outermost IASTFunctionDeclarator in declarator hierarchy
|
||||||
while (!(getterDeclarator instanceof IASTFunctionDeclarator)) {
|
while (!(getterDeclarator instanceof IASTFunctionDeclarator)) {
|
||||||
getterDeclarator = getterDeclarator.getNestedDeclarator();
|
getterDeclarator = getterDeclarator.getNestedDeclarator();
|
||||||
}
|
}
|
||||||
getter.setDeclarator((IASTFunctionDeclarator) getterDeclarator);
|
getter.setDeclarator((IASTFunctionDeclarator) getterDeclarator);
|
||||||
getter.setBody(getGetterBody(fieldName));
|
getter.setBody(getGetterBody());
|
||||||
return getter;
|
return getter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CPPASTCompoundStatement getGetterBody(IASTName fieldName) {
|
private CPPASTCompoundStatement getGetterBody() {
|
||||||
CPPASTCompoundStatement compound = new CPPASTCompoundStatement();
|
CPPASTCompoundStatement compound = new CPPASTCompoundStatement();
|
||||||
CPPASTReturnStatement returnStatement = new CPPASTReturnStatement();
|
CPPASTReturnStatement returnStatement = new CPPASTReturnStatement();
|
||||||
CPPASTIdExpression idExpr = new CPPASTIdExpression();
|
CPPASTIdExpression idExpr = new CPPASTIdExpression();
|
||||||
|
@ -70,36 +83,38 @@ public class FunctionFactory {
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IASTDeclarator getGetterDeclarator(IASTName fieldName,
|
private IASTDeclarator getGetterDeclarator(ICPPASTQualifiedName qualifiedName) {
|
||||||
IASTSimpleDeclaration fieldDeclaration, ICPPASTQualifiedName name) {
|
|
||||||
CPPASTName getterName = new CPPASTName();
|
CPPASTName getterName = new CPPASTName();
|
||||||
getterName.setName(GetterSetterNameGenerator.generateGetterName(fieldName).toCharArray());
|
getterName.setName(GetterSetterNameGenerator.generateGetterName(fieldName).toCharArray());
|
||||||
|
|
||||||
// copy declarator hierarchy
|
// Copy declarator hierarchy
|
||||||
IASTDeclarator topDeclarator = fieldDeclaration.getDeclarators()[0].copy(CopyStyle.withLocations);
|
IASTDeclarator topDeclarator = fieldDeclaration.getDeclarators()[0].copy(CopyStyle.withLocations);
|
||||||
|
|
||||||
// find the innermost declarator in hierarchy
|
// Find the innermost declarator in hierarchy
|
||||||
IASTDeclarator innermost = topDeclarator;
|
IASTDeclarator innermost = topDeclarator;
|
||||||
while (innermost.getNestedDeclarator() != null) {
|
while (innermost.getNestedDeclarator() != null) {
|
||||||
innermost = innermost.getNestedDeclarator();
|
innermost = innermost.getNestedDeclarator();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new innermost function declarator basing on the field declarator
|
// Create a new innermost function declarator based on the field declarator
|
||||||
CPPASTFunctionDeclarator functionDeclarator = new CPPASTFunctionDeclarator();
|
CPPASTFunctionDeclarator functionDeclarator = new CPPASTFunctionDeclarator();
|
||||||
functionDeclarator.setConst(true);
|
functionDeclarator.setConst(true);
|
||||||
if (name != null) {
|
if (qualifiedName != null) {
|
||||||
name.addName(getterName);
|
qualifiedName.addName(getterName);
|
||||||
functionDeclarator.setName(name);
|
functionDeclarator.setName(qualifiedName);
|
||||||
} else {
|
} else {
|
||||||
functionDeclarator.setName(getterName);
|
functionDeclarator.setName(getterName);
|
||||||
}
|
}
|
||||||
for (IASTPointerOperator pointer : innermost.getPointerOperators()){
|
for (IASTPointerOperator pointer : innermost.getPointerOperators()){
|
||||||
functionDeclarator.addPointerOperator(pointer.copy(CopyStyle.withLocations));
|
functionDeclarator.addPointerOperator(pointer.copy(CopyStyle.withLocations));
|
||||||
}
|
}
|
||||||
|
if (passByReference) {
|
||||||
|
functionDeclarator.addPointerOperator(new CPPASTReferenceOperator(false));
|
||||||
|
}
|
||||||
|
|
||||||
// replace innermost with functionDeclarator and return the whole declarator tree
|
// Replace the innermost with functionDeclarator and return the whole declarator tree
|
||||||
if (innermost == topDeclarator) {
|
if (innermost == topDeclarator) {
|
||||||
// no tree
|
// No tree
|
||||||
return functionDeclarator;
|
return functionDeclarator;
|
||||||
} else {
|
} else {
|
||||||
IASTDeclarator parent = (IASTDeclarator) innermost.getParent();
|
IASTDeclarator parent = (IASTDeclarator) innermost.getParent();
|
||||||
|
@ -108,16 +123,15 @@ public class FunctionFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IASTFunctionDefinition createSetterDefinition(IASTName fieldName,
|
public IASTFunctionDefinition createSetterDefinition(ICPPASTQualifiedName qualifiedName) {
|
||||||
IASTSimpleDeclaration fieldDeclaration, ICPPASTQualifiedName name) {
|
|
||||||
IASTFunctionDefinition setter = new CPPASTFunctionDefinition();
|
IASTFunctionDefinition setter = new CPPASTFunctionDefinition();
|
||||||
setter.setDeclSpecifier(getVoidDeclSpec());
|
setter.setDeclSpecifier(getVoidDeclSpec());
|
||||||
setter.setDeclarator(getSetterDeclarator(fieldName, fieldDeclaration, name));
|
setter.setDeclarator(getSetterDeclarator(qualifiedName));
|
||||||
setter.setBody(getSetterBody(fieldDeclaration));
|
setter.setBody(getSetterBody());
|
||||||
return setter;
|
return setter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CPPASTCompoundStatement getSetterBody(IASTSimpleDeclaration fieldDeclaration) {
|
private CPPASTCompoundStatement getSetterBody() {
|
||||||
CPPASTCompoundStatement compound = new CPPASTCompoundStatement();
|
CPPASTCompoundStatement compound = new CPPASTCompoundStatement();
|
||||||
CPPASTExpressionStatement exprStmt = new CPPASTExpressionStatement();
|
CPPASTExpressionStatement exprStmt = new CPPASTExpressionStatement();
|
||||||
CPPASTBinaryExpression binExpr = new CPPASTBinaryExpression();
|
CPPASTBinaryExpression binExpr = new CPPASTBinaryExpression();
|
||||||
|
@ -126,7 +140,7 @@ public class FunctionFactory {
|
||||||
innerDeclarator = innerDeclarator.getNestedDeclarator();
|
innerDeclarator = innerDeclarator.getNestedDeclarator();
|
||||||
}
|
}
|
||||||
IASTName fieldName = innerDeclarator.getName();
|
IASTName fieldName = innerDeclarator.getName();
|
||||||
CPPASTName parameterName = getSetterParameterName(fieldName);
|
CPPASTName parameterName = getSetterParameterName();
|
||||||
if (Arrays.equals(fieldName.getSimpleID(), parameterName.getSimpleID())) {
|
if (Arrays.equals(fieldName.getSimpleID(), parameterName.getSimpleID())) {
|
||||||
CPPASTFieldReference fieldRef = new CPPASTFieldReference();
|
CPPASTFieldReference fieldRef = new CPPASTFieldReference();
|
||||||
CPPASTLiteralExpression litExpr = new CPPASTLiteralExpression();
|
CPPASTLiteralExpression litExpr = new CPPASTLiteralExpression();
|
||||||
|
@ -147,28 +161,29 @@ public class FunctionFactory {
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CPPASTFunctionDeclarator getSetterDeclarator(IASTName fieldName,
|
private CPPASTFunctionDeclarator getSetterDeclarator(ICPPASTQualifiedName qualifiedName) {
|
||||||
IASTSimpleDeclaration fieldDeclaration, ICPPASTQualifiedName name) {
|
|
||||||
CPPASTName setterName = new CPPASTName();
|
CPPASTName setterName = new CPPASTName();
|
||||||
setterName.setName(GetterSetterNameGenerator.generateSetterName(fieldName).toCharArray());
|
setterName.setName(GetterSetterNameGenerator.generateSetterName(fieldName).toCharArray());
|
||||||
CPPASTFunctionDeclarator declarator = new CPPASTFunctionDeclarator();
|
CPPASTFunctionDeclarator declarator = new CPPASTFunctionDeclarator();
|
||||||
if (name != null) {
|
if (qualifiedName != null) {
|
||||||
name.addName(setterName);
|
qualifiedName.addName(setterName);
|
||||||
declarator.setName(name);
|
declarator.setName(qualifiedName);
|
||||||
} else {
|
} else {
|
||||||
declarator.setName(setterName);
|
declarator.setName(setterName);
|
||||||
}
|
}
|
||||||
CPPASTParameterDeclaration parameterDeclaration = new CPPASTParameterDeclaration();
|
CPPASTParameterDeclaration parameterDeclaration = new CPPASTParameterDeclaration();
|
||||||
IASTDeclarator parameterDeclarator = fieldDeclaration.getDeclarators()[0].copy(CopyStyle.withLocations);
|
IASTDeclarator parameterDeclarator = fieldDeclaration.getDeclarators()[0].copy(CopyStyle.withLocations);
|
||||||
parameterDeclarator.setName(getSetterParameterName(fieldName));
|
parameterDeclarator.setName(getSetterParameterName());
|
||||||
|
if (passByReference) {
|
||||||
|
parameterDeclarator.addPointerOperator(new CPPASTReferenceOperator(false));
|
||||||
|
}
|
||||||
parameterDeclaration.setDeclarator(parameterDeclarator);
|
parameterDeclaration.setDeclarator(parameterDeclarator);
|
||||||
parameterDeclaration.setDeclSpecifier(fieldDeclaration.getDeclSpecifier().copy(
|
parameterDeclaration.setDeclSpecifier(getParamOrReturnDeclSpecifier());
|
||||||
CopyStyle.withLocations));
|
|
||||||
declarator.addParameterDeclaration(parameterDeclaration.copy(CopyStyle.withLocations));
|
declarator.addParameterDeclaration(parameterDeclaration.copy(CopyStyle.withLocations));
|
||||||
return declarator;
|
return declarator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CPPASTName getSetterParameterName(IASTName fieldName) {
|
private CPPASTName getSetterParameterName() {
|
||||||
String parameterName = GetterSetterNameGenerator.generateSetterParameterName(fieldName);
|
String parameterName = GetterSetterNameGenerator.generateSetterParameterName(fieldName);
|
||||||
return new CPPASTName(parameterName.toCharArray());
|
return new CPPASTName(parameterName.toCharArray());
|
||||||
}
|
}
|
||||||
|
@ -179,25 +194,25 @@ public class FunctionFactory {
|
||||||
return declSpecifier;
|
return declSpecifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IASTSimpleDeclaration createGetterDeclaration(IASTName fieldName,
|
public IASTSimpleDeclaration createGetterDeclaration() {
|
||||||
IASTSimpleDeclaration fieldDeclaration) {
|
|
||||||
IASTSimpleDeclaration getter = new CPPASTSimpleDeclaration();
|
IASTSimpleDeclaration getter = new CPPASTSimpleDeclaration();
|
||||||
IASTDeclSpecifier declSpec = fieldDeclaration.getDeclSpecifier();
|
getter.setDeclSpecifier(getParamOrReturnDeclSpecifier());
|
||||||
getter.setDeclSpecifier(declSpec.copy(CopyStyle.withLocations));
|
getter.addDeclarator(getGetterDeclarator(null));
|
||||||
// TODO(sprigogin): Implement return by reference
|
|
||||||
// IType type = CPPVisitor.createType(declSpec);
|
|
||||||
// if (TypeHelper.shouldBePassedByReference(type, fieldDeclaration.getTranslationUnit())) {
|
|
||||||
// declSpec.s
|
|
||||||
// }
|
|
||||||
getter.addDeclarator(getGetterDeclarator(fieldName, fieldDeclaration, null));
|
|
||||||
return getter;
|
return getter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IASTSimpleDeclaration createSetterDeclaration(IASTName fieldName,
|
private IASTDeclSpecifier getParamOrReturnDeclSpecifier() {
|
||||||
IASTSimpleDeclaration fieldDeclaration) {
|
IASTDeclSpecifier declSpec = fieldDeclaration.getDeclSpecifier().copy(CopyStyle.withLocations);
|
||||||
|
if (passByReference) {
|
||||||
|
declSpec.setConst(true);
|
||||||
|
}
|
||||||
|
return declSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTSimpleDeclaration createSetterDeclaration() {
|
||||||
IASTSimpleDeclaration setter = new CPPASTSimpleDeclaration();
|
IASTSimpleDeclaration setter = new CPPASTSimpleDeclaration();
|
||||||
setter.setDeclSpecifier(getVoidDeclSpec());
|
setter.setDeclSpecifier(getVoidDeclSpec());
|
||||||
setter.addDeclarator(getSetterDeclarator(fieldName, fieldDeclaration, null));
|
setter.addDeclarator(getSetterDeclarator(null));
|
||||||
return setter;
|
return setter;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,14 +31,14 @@ public class GetterSetterInsertEditProvider implements Comparable<GetterSetterIn
|
||||||
|
|
||||||
private IASTSimpleDeclaration functionDeclaration;
|
private IASTSimpleDeclaration functionDeclaration;
|
||||||
private AccessorKind kind;
|
private AccessorKind kind;
|
||||||
private IASTName fieldName;
|
|
||||||
private IASTSimpleDeclaration fieldDeclaration;
|
private IASTSimpleDeclaration fieldDeclaration;
|
||||||
|
private GetterSetterFactory getterSetterFactory;
|
||||||
|
|
||||||
public GetterSetterInsertEditProvider(IASTName fieldName, IASTSimpleDeclaration fieldDeclaration,
|
public GetterSetterInsertEditProvider(IASTName fieldName, IASTSimpleDeclaration fieldDeclaration,
|
||||||
AccessorKind kind) {
|
AccessorKind kind) {
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.fieldDeclaration = fieldDeclaration;
|
this.fieldDeclaration = fieldDeclaration;
|
||||||
|
this.getterSetterFactory = new GetterSetterFactory(fieldName, fieldDeclaration);
|
||||||
|
|
||||||
createFunctionDeclaration();
|
createFunctionDeclaration();
|
||||||
}
|
}
|
||||||
|
@ -46,10 +46,10 @@ public class GetterSetterInsertEditProvider implements Comparable<GetterSetterIn
|
||||||
public void createFunctionDeclaration() {
|
public void createFunctionDeclaration() {
|
||||||
switch (this.kind) {
|
switch (this.kind) {
|
||||||
case GETTER:
|
case GETTER:
|
||||||
this.functionDeclaration = FunctionFactory.createGetterDeclaration(fieldName, fieldDeclaration);
|
this.functionDeclaration = getterSetterFactory.createGetterDeclaration();
|
||||||
break;
|
break;
|
||||||
case SETTER:
|
case SETTER:
|
||||||
this.functionDeclaration = FunctionFactory.createSetterDeclaration(fieldName, fieldDeclaration);
|
this.functionDeclaration = getterSetterFactory.createSetterDeclaration();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,23 +67,23 @@ public class GetterSetterInsertEditProvider implements Comparable<GetterSetterIn
|
||||||
IASTFunctionDefinition definition = null;
|
IASTFunctionDefinition definition = null;
|
||||||
ICPPASTQualifiedName qname;
|
ICPPASTQualifiedName qname;
|
||||||
if (qualifedName) {
|
if (qualifedName) {
|
||||||
qname = getClassname();
|
qname = getClassName();
|
||||||
} else {
|
} else {
|
||||||
qname = null;
|
qname = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case GETTER:
|
case GETTER:
|
||||||
definition = FunctionFactory.createGetterDefinition(fieldName, fieldDeclaration, qname);
|
definition = getterSetterFactory.createGetterDefinition(qname);
|
||||||
break;
|
break;
|
||||||
case SETTER:
|
case SETTER:
|
||||||
definition = FunctionFactory.createSetterDefinition(fieldName, fieldDeclaration, qname);
|
definition = getterSetterFactory.createSetterDefinition(qname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ICPPASTQualifiedName getClassname() {
|
private ICPPASTQualifiedName getClassName() {
|
||||||
IASTNode node = fieldDeclaration.getParent();
|
IASTNode node = fieldDeclaration.getParent();
|
||||||
while (!(node instanceof IASTCompositeTypeSpecifier)) {
|
while (!(node instanceof IASTCompositeTypeSpecifier)) {
|
||||||
node = node.getParent();
|
node = node.getParent();
|
||||||
|
|
|
@ -84,6 +84,7 @@ public class CReconciler extends MonoReconciler {
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
|
* @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean contains(ISchedulingRule rule) {
|
public boolean contains(ISchedulingRule rule) {
|
||||||
return rule == this;
|
return rule == this;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +92,7 @@ public class CReconciler extends MonoReconciler {
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
|
* @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean isConflicting(ISchedulingRule rule) {
|
public boolean isConflicting(ISchedulingRule rule) {
|
||||||
return rule == this;
|
return rule == this;
|
||||||
}
|
}
|
||||||
|
@ -104,26 +106,31 @@ public class CReconciler extends MonoReconciler {
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partActivated(IWorkbenchPartReference partRef) {
|
public void partActivated(IWorkbenchPartReference partRef) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partBroughtToTop(IWorkbenchPartReference partRef) {
|
public void partBroughtToTop(IWorkbenchPartReference partRef) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partClosed(IWorkbenchPartReference partRef) {
|
public void partClosed(IWorkbenchPartReference partRef) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partDeactivated(IWorkbenchPartReference partRef) {
|
public void partDeactivated(IWorkbenchPartReference partRef) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partHidden(IWorkbenchPartReference partRef) {
|
public void partHidden(IWorkbenchPartReference partRef) {
|
||||||
if (partRef.getPart(false) == fTextEditor) {
|
if (partRef.getPart(false) == fTextEditor) {
|
||||||
setEditorActive(false);
|
setEditorActive(false);
|
||||||
|
@ -132,16 +139,19 @@ public class CReconciler extends MonoReconciler {
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partInputChanged(IWorkbenchPartReference partRef) {
|
public void partInputChanged(IWorkbenchPartReference partRef) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partOpened(IWorkbenchPartReference partRef) {
|
public void partOpened(IWorkbenchPartReference partRef) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference)
|
* @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void partVisible(IWorkbenchPartReference partRef) {
|
public void partVisible(IWorkbenchPartReference partRef) {
|
||||||
if (partRef.getPart(false) == fTextEditor) {
|
if (partRef.getPart(false) == fTextEditor) {
|
||||||
CReconciler.this.scheduleReconciling();
|
CReconciler.this.scheduleReconciling();
|
||||||
|
@ -192,6 +202,7 @@ public class CReconciler extends MonoReconciler {
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.cdt.core.model.IElementChangedListener#elementChanged(org.eclipse.cdt.core.model.ElementChangedEvent)
|
* @see org.eclipse.cdt.core.model.IElementChangedListener#elementChanged(org.eclipse.cdt.core.model.ElementChangedEvent)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void elementChanged(ElementChangedEvent event) {
|
public void elementChanged(ElementChangedEvent event) {
|
||||||
if (event.getType() == ElementChangedEvent.POST_CHANGE) {
|
if (event.getType() == ElementChangedEvent.POST_CHANGE) {
|
||||||
if (isRelevantDelta(event.getDelta())) {
|
if (isRelevantDelta(event.getDelta())) {
|
||||||
|
@ -209,10 +220,7 @@ public class CReconciler extends MonoReconciler {
|
||||||
if ((flags & ICElementDelta.F_CONTENT) != 0) {
|
if ((flags & ICElementDelta.F_CONTENT) != 0) {
|
||||||
if (!fIsReconciling && isRelevantElement(delta.getElement())) {
|
if (!fIsReconciling && isRelevantElement(delta.getElement())) {
|
||||||
// mark model changed, but don't update immediately
|
// mark model changed, but don't update immediately
|
||||||
fIndexerListener.ignoreChanges(false);
|
|
||||||
setCModelChanged(true);
|
setCModelChanged(true);
|
||||||
} else if (delta.getElement() instanceof ITranslationUnit) {
|
|
||||||
fIndexerListener.ignoreChanges(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((flags & (
|
if ((flags & (
|
||||||
|
@ -237,11 +245,11 @@ public class CReconciler extends MonoReconciler {
|
||||||
|
|
||||||
private class IndexerListener implements IIndexerStateListener, IIndexChangeListener {
|
private class IndexerListener implements IIndexerStateListener, IIndexChangeListener {
|
||||||
private boolean fIndexChanged;
|
private boolean fIndexChanged;
|
||||||
private boolean fIgnoreChanges;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.cdt.core.index.IIndexerStateListener#indexChanged(org.eclipse.cdt.core.index.IIndexerStateEvent)
|
* @see org.eclipse.cdt.core.index.IIndexerStateListener#indexChanged(org.eclipse.cdt.core.index.IIndexerStateEvent)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void indexChanged(IIndexerStateEvent event) {
|
public void indexChanged(IIndexerStateEvent event) {
|
||||||
if (event.indexerIsIdle()) {
|
if (event.indexerIsIdle()) {
|
||||||
if (fIndexChanged || hasCModelChanged()) {
|
if (fIndexChanged || hasCModelChanged()) {
|
||||||
|
@ -252,25 +260,18 @@ public class CReconciler extends MonoReconciler {
|
||||||
setCModelChanged(true);
|
setCModelChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fIgnoreChanges= false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ignoreChanges(boolean ignore) {
|
|
||||||
fIgnoreChanges= ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.cdt.core.index.IIndexChangeListener#indexChanged(org.eclipse.cdt.core.index.IIndexChangeEvent)
|
* @see org.eclipse.cdt.core.index.IIndexChangeListener#indexChanged(org.eclipse.cdt.core.index.IIndexChangeEvent)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void indexChanged(IIndexChangeEvent event) {
|
public void indexChanged(IIndexChangeEvent event) {
|
||||||
if (!fIndexChanged && isRelevantProject(event.getAffectedProject())) {
|
if (!fIndexChanged && isRelevantProject(event.getAffectedProject())) {
|
||||||
if (!fIgnoreChanges || event.isCleared() || event.isReloaded() || event.hasNewFile()) {
|
fIndexChanged= true;
|
||||||
fIndexChanged= true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The reconciler's editor */
|
/** The reconciler's editor */
|
||||||
|
@ -328,6 +329,7 @@ public class CReconciler extends MonoReconciler {
|
||||||
CCorePlugin.getIndexManager().addIndexChangeListener(fIndexerListener);
|
CCorePlugin.getIndexManager().addIndexChangeListener(fIndexerListener);
|
||||||
|
|
||||||
fTriggerReconcilerJob= new SingletonJob("Trigger Reconciler", new Runnable() { //$NON-NLS-1$
|
fTriggerReconcilerJob= new SingletonJob("Trigger Reconciler", new Runnable() { //$NON-NLS-1$
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
forceReconciling();
|
forceReconciling();
|
||||||
}});
|
}});
|
||||||
|
|
|
@ -100,9 +100,11 @@ public class CSourceHover extends AbstractCEditorTextHover {
|
||||||
|
|
||||||
protected static class SingletonRule implements ISchedulingRule {
|
protected static class SingletonRule implements ISchedulingRule {
|
||||||
public static final ISchedulingRule INSTANCE = new SingletonRule();
|
public static final ISchedulingRule INSTANCE = new SingletonRule();
|
||||||
|
@Override
|
||||||
public boolean contains(ISchedulingRule rule) {
|
public boolean contains(ISchedulingRule rule) {
|
||||||
return rule == this;
|
return rule == this;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean isConflicting(ISchedulingRule rule) {
|
public boolean isConflicting(ISchedulingRule rule) {
|
||||||
return rule == this;
|
return rule == this;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +134,7 @@ public class CSourceHover extends AbstractCEditorTextHover {
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable#runOnAST(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit)
|
* @see org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable#runOnAST(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
|
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
|
||||||
if (ast != null) {
|
if (ast != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -637,12 +640,8 @@ public class CSourceHover extends AbstractCEditorTextHover {
|
||||||
|
|
||||||
String[] sourceLines= Strings.convertIntoLines(source);
|
String[] sourceLines= Strings.convertIntoLines(source);
|
||||||
String firstLine= sourceLines[0];
|
String firstLine= sourceLines[0];
|
||||||
if (firstLine.length() > 0 && !Character.isWhitespace(firstLine.charAt(0)))
|
boolean ignoreFirstLine= firstLine.length() > 0 && !Character.isWhitespace(firstLine.charAt(0));
|
||||||
sourceLines[0]= ""; //$NON-NLS-1$
|
Strings.trimIndentation(sourceLines, getTabWidth(), getTabWidth(), !ignoreFirstLine);
|
||||||
Strings.trimIndentation(sourceLines, getTabWidth(), getTabWidth());
|
|
||||||
|
|
||||||
if (!Character.isWhitespace(firstLine.charAt(0)))
|
|
||||||
sourceLines[0]= firstLine;
|
|
||||||
|
|
||||||
source = Strings.concatenate(sourceLines, delim);
|
source = Strings.concatenate(sourceLines, delim);
|
||||||
return source;
|
return source;
|
||||||
|
@ -797,6 +796,7 @@ public class CSourceHover extends AbstractCEditorTextHover {
|
||||||
@Override
|
@Override
|
||||||
public IInformationControlCreator getHoverControlCreator() {
|
public IInformationControlCreator getHoverControlCreator() {
|
||||||
return new IInformationControlCreator() {
|
return new IInformationControlCreator() {
|
||||||
|
@Override
|
||||||
public IInformationControl createInformationControl(Shell parent) {
|
public IInformationControl createInformationControl(Shell parent) {
|
||||||
IEditorPart editor= getEditor();
|
IEditorPart editor= getEditor();
|
||||||
int orientation= SWT.NONE;
|
int orientation= SWT.NONE;
|
||||||
|
@ -814,6 +814,7 @@ public class CSourceHover extends AbstractCEditorTextHover {
|
||||||
@Override
|
@Override
|
||||||
public IInformationControlCreator getInformationPresenterControlCreator() {
|
public IInformationControlCreator getInformationPresenterControlCreator() {
|
||||||
return new IInformationControlCreator() {
|
return new IInformationControlCreator() {
|
||||||
|
@Override
|
||||||
public IInformationControl createInformationControl(Shell parent) {
|
public IInformationControl createInformationControl(Shell parent) {
|
||||||
IEditorPart editor= getEditor();
|
IEditorPart editor= getEditor();
|
||||||
int orientation= SWT.NONE;
|
int orientation= SWT.NONE;
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
||||||
|
|
||||||
private String fErrorMessage;
|
private String fErrorMessage;
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
|
public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
|
||||||
List<ICompletionProposal> proposals= Collections.emptyList();
|
List<ICompletionProposal> proposals= Collections.emptyList();
|
||||||
fErrorMessage= null;
|
fErrorMessage= null;
|
||||||
|
@ -81,17 +82,21 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
||||||
return proposals;
|
return proposals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<IContextInformation> computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
|
public List<IContextInformation> computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getErrorMessage() {
|
public String getErrorMessage() {
|
||||||
return fErrorMessage;
|
return fErrorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sessionEnded() {
|
public void sessionEnded() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sessionStarted() {
|
public void sessionStarted() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +262,9 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
||||||
final int prefixLength = namePrefix.length();
|
final int prefixLength = namePrefix.length();
|
||||||
final IProject project= tu.getCProject().getProject();
|
final IProject project= tu.getCProject().getProject();
|
||||||
File[] files= fileDir.listFiles();
|
File[] files= fileDir.listFiles();
|
||||||
|
if (files == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(namePrefix);
|
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(namePrefix);
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
final String name= file.getName();
|
final String name= file.getName();
|
||||||
|
@ -311,6 +319,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
||||||
final IProject project= tu.getCProject().getProject();
|
final IProject project= tu.getCProject().getProject();
|
||||||
parent.accept(new IResourceProxyVisitor() {
|
parent.accept(new IResourceProxyVisitor() {
|
||||||
boolean fFirstVisit= true;
|
boolean fFirstVisit= true;
|
||||||
|
@Override
|
||||||
public boolean visit(IResourceProxy proxy) throws CoreException {
|
public boolean visit(IResourceProxy proxy) throws CoreException {
|
||||||
final int type= proxy.getType();
|
final int type= proxy.getType();
|
||||||
final String name= proxy.getName();
|
final String name= proxy.getName();
|
||||||
|
|
|
@ -192,8 +192,8 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
|
||||||
// editor.setAction("AddDelegateMethods", fAddDelegateMethods); //$NON-NLS-1$
|
// editor.setAction("AddDelegateMethods", fAddDelegateMethods); //$NON-NLS-1$
|
||||||
//
|
//
|
||||||
// fAddUnimplementedConstructors= new AddUnimplementedConstructorsAction(editor);
|
// fAddUnimplementedConstructors= new AddUnimplementedConstructorsAction(editor);
|
||||||
// fAddUnimplementedConstructors.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_UNIMPLEMENTED_CONTRUCTORS);
|
// fAddUnimplementedConstructors.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_UNIMPLEMENTED_CONSTRUCTORS);
|
||||||
// editor.setAction("AddUnimplementedConstructors", fAddUnimplementedConstructors); //$NON-NLS-1$
|
// editor.setAction("AddUnimplementedConstructors", fAddUnimplementedConstructors); //$NON-NLS-1$
|
||||||
//
|
//
|
||||||
// fGenerateConstructorUsingFields= new GenerateNewConstructorUsingFieldsAction(editor);
|
// fGenerateConstructorUsingFields= new GenerateNewConstructorUsingFieldsAction(editor);
|
||||||
// fGenerateConstructorUsingFields.setActionDefinitionId(ICEditorActionDefinitionIds.GENERATE_CONSTRUCTOR_USING_FIELDS);
|
// fGenerateConstructorUsingFields.setActionDefinitionId(ICEditorActionDefinitionIds.GENERATE_CONSTRUCTOR_USING_FIELDS);
|
||||||
|
@ -277,8 +277,8 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
|
||||||
// fAddDelegateMethods.setActionDefinitionId(ICEditorActionDefinitionIds.CREATE_DELEGATE_METHODS);
|
// fAddDelegateMethods.setActionDefinitionId(ICEditorActionDefinitionIds.CREATE_DELEGATE_METHODS);
|
||||||
//
|
//
|
||||||
// fAddUnimplementedConstructors= new AddUnimplementedConstructorsAction(site);
|
// fAddUnimplementedConstructors= new AddUnimplementedConstructorsAction(site);
|
||||||
// fAddUnimplementedConstructors.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_UNIMPLEMENTED_CONTRUCTORS);
|
// fAddUnimplementedConstructors.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_UNIMPLEMENTED_CONSTRUCTORS);
|
||||||
//
|
//
|
||||||
// fGenerateConstructorUsingFields= new GenerateNewConstructorUsingFieldsAction(site);
|
// fGenerateConstructorUsingFields= new GenerateNewConstructorUsingFieldsAction(site);
|
||||||
// fGenerateConstructorUsingFields.setActionDefinitionId(ICEditorActionDefinitionIds.GENERATE_CONSTRUCTOR_USING_FIELDS);
|
// fGenerateConstructorUsingFields.setActionDefinitionId(ICEditorActionDefinitionIds.GENERATE_CONSTRUCTOR_USING_FIELDS);
|
||||||
//
|
//
|
||||||
|
|
|
@ -80,7 +80,7 @@ public abstract class AbstractErrorParserBlock extends AbstractCOptionPage {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public AbstractErrorParserBlock(Preferences prefs) {
|
public AbstractErrorParserBlock(Preferences prefs) {
|
||||||
this();
|
this();
|
||||||
// usingDeprecatedContructor = true;
|
// usingDeprecatedConstructor = true;
|
||||||
fPrefs = prefs;
|
fPrefs = prefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
dsf/org.eclipse.cdt.dsf/.settings/.api_filters
Normal file
11
dsf/org.eclipse.cdt.dsf/.settings/.api_filters
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<component id="org.eclipse.cdt.dsf" version="2">
|
||||||
|
<resource path="src/org/eclipse/cdt/dsf/concurrent/Transaction.java" type="org.eclipse.cdt.dsf.concurrent.Transaction">
|
||||||
|
<filter comment="Utility is not in common use. I changed erasure type for argument, but at worse this should only cause a warning." id="420679712">
|
||||||
|
<message_arguments>
|
||||||
|
<message_argument value="org.eclipse.cdt.dsf.concurrent.Transaction.validate(ICache<?>[])"/>
|
||||||
|
<message_argument value="T"/>
|
||||||
|
</message_arguments>
|
||||||
|
</filter>
|
||||||
|
</resource>
|
||||||
|
</component>
|
|
@ -154,6 +154,27 @@ public abstract class AbstractCache<V> implements ICache<V> {
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void completeWaitingRms() {
|
||||||
|
Object waiting = null;
|
||||||
|
synchronized(this) {
|
||||||
|
waiting = fWaitingList;
|
||||||
|
fWaitingList = null;
|
||||||
|
}
|
||||||
|
if (waiting != null) {
|
||||||
|
if (waiting instanceof RequestMonitor) {
|
||||||
|
completeWaitingRm((RequestMonitor)waiting);
|
||||||
|
} else if (waiting instanceof RequestMonitor[]) {
|
||||||
|
RequestMonitor[] waitingList = (RequestMonitor[])waiting;
|
||||||
|
for (int i = 0; i < waitingList.length; i++) {
|
||||||
|
if (waitingList[i] != null) {
|
||||||
|
completeWaitingRm(waitingList[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waiting = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void completeWaitingRm(RequestMonitor rm) {
|
private void completeWaitingRm(RequestMonitor rm) {
|
||||||
rm.setStatus(fStatus);
|
rm.setStatus(fStatus);
|
||||||
|
@ -300,23 +321,33 @@ public abstract class AbstractCache<V> implements ICache<V> {
|
||||||
fStatus = status;
|
fStatus = status;
|
||||||
fValid = true;
|
fValid = true;
|
||||||
|
|
||||||
Object waiting = null;
|
completeWaitingRms();
|
||||||
synchronized(this) {
|
|
||||||
waiting = fWaitingList;
|
|
||||||
fWaitingList = null;
|
|
||||||
}
|
|
||||||
if (waiting != null) {
|
|
||||||
if (waiting instanceof RequestMonitor) {
|
|
||||||
completeWaitingRm((RequestMonitor)waiting);
|
|
||||||
} else if (waiting instanceof RequestMonitor[]) {
|
|
||||||
RequestMonitor[] waitingList = (RequestMonitor[])waiting;
|
|
||||||
for (int i = 0; i < waitingList.length; i++) {
|
|
||||||
if (waitingList[i] != null) {
|
|
||||||
completeWaitingRm(waitingList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
waiting = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the set and reset operations in one step This allows the cache to
|
||||||
|
* remain in invalid state, but to notify any waiting listeners that the state of
|
||||||
|
* the cache has changed.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* The data that should be returned to any clients waiting for
|
||||||
|
* cache data and for clients requesting data until the cache is
|
||||||
|
* invalidated.
|
||||||
|
* @status The status that should be returned to any clients waiting for
|
||||||
|
* cache data and for clients requesting data until the cache is
|
||||||
|
* invalidated
|
||||||
|
*
|
||||||
|
* @see #reset(Object, IStatus)
|
||||||
|
* @since 2.3
|
||||||
|
*/
|
||||||
|
protected void setAndReset(V data, IStatus status) {
|
||||||
|
assert fExecutor.getDsfExecutor().isInExecutorThread();
|
||||||
|
|
||||||
|
fData = data;
|
||||||
|
fStatus = status;
|
||||||
|
fValid = false;
|
||||||
|
|
||||||
|
completeWaitingRms();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,7 @@ abstract public class RangeCache<V> {
|
||||||
protected List<V> process() throws InvalidCacheException, CoreException {
|
protected List<V> process() throws InvalidCacheException, CoreException {
|
||||||
clearCanceledRequests();
|
clearCanceledRequests();
|
||||||
|
|
||||||
List<ICache<?>> transactionRequests = getRequests(fOffset, fCount);
|
List<Request> transactionRequests = getRequests(fOffset, fCount);
|
||||||
|
|
||||||
validate(transactionRequests);
|
validate(transactionRequests);
|
||||||
|
|
||||||
return makeElementsListFromRequests(transactionRequests, fOffset, fCount);
|
return makeElementsListFromRequests(transactionRequests, fOffset, fCount);
|
||||||
|
@ -156,7 +155,7 @@ abstract public class RangeCache<V> {
|
||||||
public ICache<List<V>> getRange(final long offset, final int count) {
|
public ICache<List<V>> getRange(final long offset, final int count) {
|
||||||
assert fExecutor.getDsfExecutor().isInExecutorThread();
|
assert fExecutor.getDsfExecutor().isInExecutorThread();
|
||||||
|
|
||||||
List<ICache<?>> requests = getRequests(offset, count);
|
List<Request> requests = getRequests(offset, count);
|
||||||
|
|
||||||
RequestCache<List<V>> range = new RequestCache<List<V>>(fExecutor) {
|
RequestCache<List<V>> range = new RequestCache<List<V>>(fExecutor) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -232,8 +231,8 @@ abstract public class RangeCache<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ICache<?>> getRequests(long fOffset, int fCount) {
|
private List<Request> getRequests(long fOffset, int fCount) {
|
||||||
List<ICache<?>> requests = new ArrayList<ICache<?>>(1);
|
List<Request> requests = new ArrayList<Request>(1);
|
||||||
|
|
||||||
// Create a new request for the data to retrieve.
|
// Create a new request for the data to retrieve.
|
||||||
Request current = new Request(fOffset, fCount);
|
Request current = new Request(fOffset, fCount);
|
||||||
|
@ -252,7 +251,7 @@ abstract public class RangeCache<V> {
|
||||||
// Adjust the beginning of the requested range of data. If there
|
// Adjust the beginning of the requested range of data. If there
|
||||||
// is already an overlapping range in front of the requested range,
|
// is already an overlapping range in front of the requested range,
|
||||||
// then use it.
|
// then use it.
|
||||||
private Request adjustRequestHead(Request request, List<ICache<?>> transactionRequests, long offset, int count) {
|
private Request adjustRequestHead(Request request, List<Request> transactionRequests, long offset, int count) {
|
||||||
SortedSet<Request> headRequests = fRequests.headSet(request);
|
SortedSet<Request> headRequests = fRequests.headSet(request);
|
||||||
if (!headRequests.isEmpty()) {
|
if (!headRequests.isEmpty()) {
|
||||||
Request headRequest = headRequests.last();
|
Request headRequest = headRequests.last();
|
||||||
|
@ -276,7 +275,7 @@ abstract public class RangeCache<V> {
|
||||||
* @param transactionRequests
|
* @param transactionRequests
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Request adjustRequestTail(Request current, List<ICache<?>> transactionRequests, long offset, int count) {
|
private Request adjustRequestTail(Request current, List<Request> transactionRequests, long offset, int count) {
|
||||||
// Create a duplicate of the tailSet, in order to avoid a concurrent modification exception.
|
// Create a duplicate of the tailSet, in order to avoid a concurrent modification exception.
|
||||||
List<Request> tailSet = new ArrayList<Request>(fRequests.tailSet(current));
|
List<Request> tailSet = new ArrayList<Request>(fRequests.tailSet(current));
|
||||||
|
|
||||||
|
@ -313,14 +312,13 @@ abstract public class RangeCache<V> {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<V> makeElementsListFromRequests(List<ICache<?>> requests, long offset, int count) {
|
private List<V> makeElementsListFromRequests(List<Request> requests, long offset, int count) {
|
||||||
List<V> retVal = new ArrayList<V>(count);
|
List<V> retVal = new ArrayList<V>(count);
|
||||||
long index = offset;
|
long index = offset;
|
||||||
long end = offset + count;
|
long end = offset + count;
|
||||||
int requestIdx = 0;
|
int requestIdx = 0;
|
||||||
while (index < end ) {
|
while (index < end ) {
|
||||||
@SuppressWarnings("unchecked")
|
Request request = requests.get(requestIdx);
|
||||||
Request request = (Request)requests.get(requestIdx);
|
|
||||||
if (index < request.fOffset + request.fCount) {
|
if (index < request.fOffset + request.fCount) {
|
||||||
retVal.add( request.getData().get((int)(index - request.fOffset)) );
|
retVal.add( request.getData().get((int)(index - request.fOffset)) );
|
||||||
index ++;
|
index ++;
|
||||||
|
|
|
@ -94,4 +94,13 @@ public abstract class RequestCache<V> extends AbstractCache<V> {
|
||||||
}
|
}
|
||||||
super.set(data, status);
|
super.set(data, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reset() {
|
||||||
|
if (fRm != null) {
|
||||||
|
fRm.cancel();
|
||||||
|
fRm = null;
|
||||||
|
}
|
||||||
|
super.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,10 @@ public abstract class Transaction<V> {
|
||||||
* logic once the cache object has been updated from the source.
|
* logic once the cache object has been updated from the source.
|
||||||
*
|
*
|
||||||
* @return the cached data if it's valid, otherwise an exception is thrown
|
* @return the cached data if it's valid, otherwise an exception is thrown
|
||||||
* @throws InvalidCacheException
|
* @throws Transaction.InvalidCacheException Exception indicating that a
|
||||||
* @throws CoreException
|
* cache is not valid and transaction will need to be rescheduled.
|
||||||
|
* @throws CoreException Exception indicating that one of the caches is
|
||||||
|
* in error state and transaction cannot be processed.
|
||||||
*/
|
*/
|
||||||
abstract protected V process() throws InvalidCacheException, CoreException;
|
abstract protected V process() throws InvalidCacheException, CoreException;
|
||||||
|
|
||||||
|
@ -149,19 +151,20 @@ public abstract class Transaction<V> {
|
||||||
* See {@link #validate(RequestCache)}. This variant simply validates
|
* See {@link #validate(RequestCache)}. This variant simply validates
|
||||||
* multiple cache objects.
|
* multiple cache objects.
|
||||||
*/
|
*/
|
||||||
public void validate(ICache<?> ... caches) throws InvalidCacheException, CoreException {
|
public <T> void validate(ICache<?> ... caches) throws InvalidCacheException, CoreException {
|
||||||
validate(Arrays.asList(caches));
|
validate(Arrays.asList(caches));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link #validate(RequestCache)}. This variant simply validates
|
* See {@link #validate(RequestCache)}. This variant simply validates
|
||||||
* multiple cache objects.
|
* multiple cache objects.
|
||||||
*/
|
*/
|
||||||
public void validate(Iterable<ICache<?>> caches) throws InvalidCacheException, CoreException {
|
public void validate(@SuppressWarnings("rawtypes") Iterable caches) throws InvalidCacheException, CoreException {
|
||||||
// Check if any of the caches have errors:
|
// Check if any of the caches have errors:
|
||||||
boolean allValid = true;
|
boolean allValid = true;
|
||||||
|
|
||||||
for (ICache<?> cache : caches) {
|
for (Object cacheObj : caches) {
|
||||||
|
ICache<?> cache = (ICache<?>)cacheObj;
|
||||||
if (cache.isValid()) {
|
if (cache.isValid()) {
|
||||||
if (!cache.getStatus().isOK()) {
|
if (!cache.getStatus().isOK()) {
|
||||||
throw new CoreException(cache.getStatus());
|
throw new CoreException(cache.getStatus());
|
||||||
|
@ -171,9 +174,9 @@ public abstract class Transaction<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!allValid) {
|
if (!allValid) {
|
||||||
// Throw the invalid cache exception, but first schedule a
|
// Throw the invalid cache exception, but first schedule a
|
||||||
// re-attempt of the transaction logic, to occur when the
|
// re-attempt of the transaction logic, to occur when the
|
||||||
// stale/unset cache objects have been updated
|
// stale/unset cache objects have been updated
|
||||||
CountingRequestMonitor countringRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), fRm) {
|
CountingRequestMonitor countringRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), fRm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
|
@ -181,7 +184,8 @@ public abstract class Transaction<V> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (ICache<?> cache : caches) {
|
for (Object cacheObj : caches) {
|
||||||
|
ICache<?> cache = (ICache<?>)cacheObj;
|
||||||
if (!cache.isValid()) {
|
if (!cache.isValid()) {
|
||||||
cache.update(countringRm);
|
cache.update(countringRm);
|
||||||
count++;
|
count++;
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
//#ifdef exercises
|
||||||
|
package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
|
//#else
|
||||||
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ICache;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateInDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Transaction;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data generator which performs a sum computation on data retrieved from a
|
||||||
|
* number of other data generators. The data retrieval from other generators
|
||||||
|
* is performed using ACPM caches and the result is calculated once all caches
|
||||||
|
* are valid.
|
||||||
|
* <p>
|
||||||
|
* Unlike {@link AsyncSumDataGenerator}, this data generator listens to events
|
||||||
|
* from the individual the data providers. Theve events are used to
|
||||||
|
* invalidate caches to make sure that they don't return incorrect data. This
|
||||||
|
* generator also sends out events to its clients to notify them to update, or
|
||||||
|
* invalidate their caches.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class ACPMSumDataGenerator
|
||||||
|
implements IDataGenerator, IDataGenerator.Listener
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DSF executor used to serialize data access within this data generator.
|
||||||
|
*/
|
||||||
|
final private DsfExecutor fExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data generators to retrieve original data to perform calculations on.
|
||||||
|
* The generators are accessed through the cache manager wrappers.
|
||||||
|
*/
|
||||||
|
final private DataGeneratorCacheManager[] fDataGeneratorCMs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of listeners for this data generator.
|
||||||
|
*/
|
||||||
|
final private List<Listener> fListeners = new LinkedList<Listener>();
|
||||||
|
|
||||||
|
public ACPMSumDataGenerator(DsfExecutor executor,
|
||||||
|
IDataGenerator[] generators)
|
||||||
|
{
|
||||||
|
fExecutor = executor;
|
||||||
|
|
||||||
|
// Create wrappers for data generators and add ourselves as listener
|
||||||
|
// to their events.
|
||||||
|
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
|
||||||
|
ImmediateInDsfExecutor immediateExecutor =
|
||||||
|
new ImmediateInDsfExecutor(fExecutor);
|
||||||
|
for (int i = 0; i < generators.length; i++) {
|
||||||
|
fDataGeneratorCMs[i] = new DataGeneratorCacheManager(
|
||||||
|
immediateExecutor, generators[i]);
|
||||||
|
generators[i].addListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getCount(final DataRequestMonitor<Integer> rm) {
|
||||||
|
// Artificially delay the retrieval of the sum data to simulate
|
||||||
|
// real processing time.
|
||||||
|
fExecutor.schedule( new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
// Create the transaction here to put all the ugly
|
||||||
|
// code in one place.
|
||||||
|
new Transaction<Integer>() {
|
||||||
|
@Override
|
||||||
|
protected Integer process()
|
||||||
|
throws Transaction.InvalidCacheException,
|
||||||
|
CoreException
|
||||||
|
{
|
||||||
|
return processCount(this);
|
||||||
|
}
|
||||||
|
}.request(rm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the calculation to get the max count for the given transaction.
|
||||||
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
|
* @return Calculated count.
|
||||||
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
|
* @throws CoreException See {@link Transaction#process}
|
||||||
|
*/
|
||||||
|
private Integer processCount(Transaction<Integer> transaction)
|
||||||
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
|
{
|
||||||
|
// Assemble all needed count caches into a collection.
|
||||||
|
List<ICache<Integer>> countCaches =
|
||||||
|
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
||||||
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
|
countCaches.add(dataGeneratorCM.getCount());
|
||||||
|
}
|
||||||
|
// Validate all count caches at once. This executes needed requests
|
||||||
|
// in parallel.
|
||||||
|
transaction.validate(countCaches);
|
||||||
|
|
||||||
|
// Calculate the max value and return.
|
||||||
|
int maxCount = 0;
|
||||||
|
for (ICache<Integer> countCache : countCaches) {
|
||||||
|
maxCount = Math.max(maxCount, countCache.getData());
|
||||||
|
}
|
||||||
|
return maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getValue(final int index, final DataRequestMonitor<Integer> rm)
|
||||||
|
{
|
||||||
|
// Add a processing delay.
|
||||||
|
fExecutor.schedule( new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
new Transaction<Integer>() {
|
||||||
|
@Override
|
||||||
|
protected Integer process()
|
||||||
|
throws Transaction.InvalidCacheException,
|
||||||
|
CoreException
|
||||||
|
{
|
||||||
|
return processValue(this, index);
|
||||||
|
}
|
||||||
|
}.request(rm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the calculation to get the sum of values at given index.
|
||||||
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
|
* @param index Index of value to calculate.
|
||||||
|
* @return Calculated value.
|
||||||
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
|
* @throws CoreException See {@link Transaction#process}
|
||||||
|
*/
|
||||||
|
private Integer processValue(Transaction<Integer> transaction, int index)
|
||||||
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
|
{
|
||||||
|
List<ICache<Integer>> valueCaches =
|
||||||
|
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
||||||
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
|
valueCaches.add(dataGeneratorCM.getValue(index));
|
||||||
|
}
|
||||||
|
// Validate all value caches at once. This executes needed requests
|
||||||
|
// in parallel.
|
||||||
|
transaction.validate(valueCaches);
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
for (ICache<Integer> valueCache : valueCaches) {
|
||||||
|
sum += valueCache.getData();
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown(final RequestMonitor rm) {
|
||||||
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
|
dataGeneratorCM.getDataGenerator().removeListener(this);
|
||||||
|
dataGeneratorCM.dispose();
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(final Listener listener) {
|
||||||
|
// Must access fListeners on executor thread.
|
||||||
|
try {
|
||||||
|
fExecutor.execute( new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
fListeners.add(listener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(final Listener listener) {
|
||||||
|
// Must access fListeners on executor thread.
|
||||||
|
try {
|
||||||
|
fExecutor.execute( new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
fListeners.remove(listener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void countChanged() {
|
||||||
|
// Must access fListeners on executor thread.
|
||||||
|
try {
|
||||||
|
fExecutor.execute( new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
for (Listener listener : fListeners) {
|
||||||
|
listener.countChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void valuesChanged(final Set<Integer> changed) {
|
||||||
|
// Must access fListeners on executor thread.
|
||||||
|
try {
|
||||||
|
fExecutor.execute( new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
for (Object listener : fListeners) {
|
||||||
|
((Listener)listener).valuesChanged(changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,482 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
//#ifdef exercises
|
||||||
|
package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
|
//#else
|
||||||
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ICache;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateInDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Transaction;
|
||||||
|
import org.eclipse.cdt.dsf.ui.concurrent.DisplayDsfExecutor;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.jface.viewers.ILazyContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.TableViewer;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.graphics.Font;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data viewer based on a table, which reads data from multiple data
|
||||||
|
* providers using ACPM methods and performs a computation on the
|
||||||
|
* retrieved data.
|
||||||
|
* <p>
|
||||||
|
* This example builds on the {@link AsyncSumDataViewer} example. It
|
||||||
|
* demonstrates using ACPM to solve the data consistency problem when
|
||||||
|
* retrieving data from multiple sources asynchronously.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@ConfinedToDsfExecutor("fDisplayExecutor")
|
||||||
|
public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
|
{
|
||||||
|
/** View update frequency interval. */
|
||||||
|
final private static int UPDATE_INTERVAL = 10000;
|
||||||
|
|
||||||
|
/** Executor to use instead of Display.asyncExec(). **/
|
||||||
|
@ThreadSafe
|
||||||
|
final private DsfExecutor fDisplayExecutor;
|
||||||
|
|
||||||
|
/** Executor to use when retrieving data from data providers */
|
||||||
|
@ThreadSafe
|
||||||
|
final private ImmediateInDsfExecutor fDataExecutor;
|
||||||
|
|
||||||
|
// The viewer and generator that this content provider using.
|
||||||
|
final private TableViewer fViewer;
|
||||||
|
final private DataGeneratorCacheManager[] fDataGeneratorCMs;
|
||||||
|
final private DataGeneratorCacheManager fSumGeneratorCM;
|
||||||
|
|
||||||
|
// Fields used in request cancellation logic.
|
||||||
|
private List<ValueRequestMonitor> fItemDataRequestMonitors =
|
||||||
|
new LinkedList<ValueRequestMonitor>();
|
||||||
|
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
private int fCancelCallsPending = 0;
|
||||||
|
private Future<?> fRefreshFuture;
|
||||||
|
|
||||||
|
public ACPMSumDataViewer(TableViewer viewer,
|
||||||
|
ImmediateInDsfExecutor dataExecutor, IDataGenerator[] generators,
|
||||||
|
IDataGenerator sumGenerator)
|
||||||
|
{
|
||||||
|
fViewer = viewer;
|
||||||
|
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
||||||
|
fViewer.getTable().getDisplay());
|
||||||
|
fDataExecutor = dataExecutor;
|
||||||
|
|
||||||
|
// Create wrappers for data generators. Don't need to register as
|
||||||
|
// listeners to generator events because the cache managers ensure data
|
||||||
|
// are already registered for them.
|
||||||
|
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
|
||||||
|
for (int i = 0; i < generators.length; i++) {
|
||||||
|
fDataGeneratorCMs[i] =
|
||||||
|
new DataGeneratorCacheManager(fDataExecutor, generators[i]);
|
||||||
|
}
|
||||||
|
fSumGeneratorCM =
|
||||||
|
new DataGeneratorCacheManager(fDataExecutor, sumGenerator);
|
||||||
|
|
||||||
|
// Schedule a task to refresh the viewer periodically.
|
||||||
|
fRefreshFuture = fDisplayExecutor.scheduleAtFixedRate(
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
queryItemCount();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
// Cancel the periodic task of refreshing the view.
|
||||||
|
fRefreshFuture.cancel(false);
|
||||||
|
|
||||||
|
// Need to dispose cache managers that were created in this class. This
|
||||||
|
// needs to be done on the cache manager's thread.
|
||||||
|
Query<Object> disposeCacheManagersQuery = new Query<Object>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<Object> rm) {
|
||||||
|
fSumGeneratorCM.dispose();
|
||||||
|
for (DataGeneratorCacheManager dataGeneratorCM :
|
||||||
|
fDataGeneratorCMs)
|
||||||
|
{
|
||||||
|
dataGeneratorCM.dispose();
|
||||||
|
}
|
||||||
|
rm.setData(new Object());
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fDataExecutor.execute(disposeCacheManagersQuery);
|
||||||
|
try {
|
||||||
|
disposeCacheManagersQuery.get();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {}
|
||||||
|
catch (ExecutionException e) {}
|
||||||
|
|
||||||
|
// Cancel any outstanding data requests.
|
||||||
|
for (ValueRequestMonitor rm : fItemDataRequestMonitors) {
|
||||||
|
rm.cancel();
|
||||||
|
}
|
||||||
|
fItemDataRequestMonitors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
|
||||||
|
// Set the initial count to the viewer after the input is set.
|
||||||
|
queryItemCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateElement(final int index) {
|
||||||
|
// Calculate the visible index range.
|
||||||
|
final int topIdx = fViewer.getTable().getTopIndex();
|
||||||
|
final int botIdx = topIdx + getVisibleItemCount(topIdx);
|
||||||
|
|
||||||
|
// Request the item for the given index.
|
||||||
|
queryValue(index);
|
||||||
|
|
||||||
|
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
||||||
|
// calls to be combined together improving performance of the viewer.
|
||||||
|
fCancelCallsPending++;
|
||||||
|
fDisplayExecutor.execute(
|
||||||
|
new Runnable() { public void run() {
|
||||||
|
cancelStaleRequests(topIdx, botIdx);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the number of visible items based on the top item index and
|
||||||
|
* table bounds.
|
||||||
|
* @param top Index of top item.
|
||||||
|
* @return calculated number of items in viewer
|
||||||
|
*/
|
||||||
|
private int getVisibleItemCount(int top) {
|
||||||
|
Table table = fViewer.getTable();
|
||||||
|
int itemCount = table.getItemCount();
|
||||||
|
return Math.min(
|
||||||
|
(table.getBounds().height / table.getItemHeight()) + 2,
|
||||||
|
itemCount - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the current count. When a new count is set to viewer, the viewer
|
||||||
|
* will refresh all items as well.
|
||||||
|
*/
|
||||||
|
private void queryItemCount() {
|
||||||
|
// Create the request monitor to collect the count. This request
|
||||||
|
// monitor will be completed by the following transaction.
|
||||||
|
final DataRequestMonitor<Integer> rm =
|
||||||
|
new DataRequestMonitor<Integer>(fDisplayExecutor, null)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
setCountToViewer(getData());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void handleRejectedExecutionException() {} // Shutting down, ignore.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use a transaction, even with a single cache. This will ensure that
|
||||||
|
// if the cache is reset during processing by an event. The request
|
||||||
|
// for data will be re-issued.
|
||||||
|
fDataExecutor.execute(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
new Transaction<Integer>() {
|
||||||
|
@Override
|
||||||
|
protected Integer process()
|
||||||
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
|
{
|
||||||
|
return processCount(this);
|
||||||
|
}
|
||||||
|
}.request(rm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the count retrieval from the sum data generator.
|
||||||
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
|
* @return Calculated count.
|
||||||
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
|
* @throws CoreException See {@link Transaction#process}
|
||||||
|
*/
|
||||||
|
private Integer processCount(Transaction<Integer> transaction)
|
||||||
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
|
{
|
||||||
|
ICache<Integer> countCache = fSumGeneratorCM.getCount();
|
||||||
|
transaction.validate(countCache);
|
||||||
|
return countCache.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the givne count to the viewer. This will cause the viewer will
|
||||||
|
* refresh all items' data as well.
|
||||||
|
* <p>Note: This method must be called in the display thread. </p>
|
||||||
|
* @param count New count to set to viewer.
|
||||||
|
*/
|
||||||
|
private void setCountToViewer(int count) {
|
||||||
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
|
fViewer.setItemCount(count);
|
||||||
|
fViewer.getTable().clearAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the current value for given index.
|
||||||
|
*/
|
||||||
|
private void queryValue(final int index) {
|
||||||
|
// Create the request monitor to collect the value. This request
|
||||||
|
// monitor will be completed by the following transaction.
|
||||||
|
final ValueRequestMonitor rm = new ValueRequestMonitor(index) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
fItemDataRequestMonitors.remove(this);
|
||||||
|
if (isSuccess()) {
|
||||||
|
setValueToViewer(index, getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void handleRejectedExecutionException() {
|
||||||
|
// Shutting down, ignore.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save the value request monitor, to cancel it if the view is
|
||||||
|
// scrolled.
|
||||||
|
fItemDataRequestMonitors.add(rm);
|
||||||
|
|
||||||
|
// Use a transaction, even with a single cache. This will ensure that
|
||||||
|
// if the cache is reset during processing by an event. The request
|
||||||
|
// for data will be re-issued.
|
||||||
|
fDataExecutor.execute(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
new Transaction<String>() {
|
||||||
|
@Override
|
||||||
|
protected String process()
|
||||||
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
|
{
|
||||||
|
return processValue(this, index);
|
||||||
|
}
|
||||||
|
}.request(rm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the view value to the viewer.
|
||||||
|
* <p>Note: This method must be called in the display thread. </p>
|
||||||
|
* @param index Index of value to set.
|
||||||
|
* @param value New value.
|
||||||
|
*/
|
||||||
|
private void setValueToViewer(int index, String value) {
|
||||||
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
|
fViewer.replace(value, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the calculation compose the string with data provider values
|
||||||
|
* and the sum. This implementation also validates the result.
|
||||||
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
|
* @param index Index of value to calculate.
|
||||||
|
* @return Calculated value.
|
||||||
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
|
* @throws CoreException See {@link Transaction#process}
|
||||||
|
*/
|
||||||
|
private String processValue(Transaction<String> transaction, int index)
|
||||||
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
|
{
|
||||||
|
List<ICache<Integer>> valueCaches =
|
||||||
|
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
||||||
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
|
valueCaches.add(dataGeneratorCM.getValue(index));
|
||||||
|
}
|
||||||
|
// Validate all value caches at once. This executes needed requests
|
||||||
|
// in parallel.
|
||||||
|
transaction.validate(valueCaches);
|
||||||
|
|
||||||
|
// TODO: evaluate sum generator cache in parallel with value caches.
|
||||||
|
ICache<Integer> sumCache = fSumGeneratorCM.getValue(index);
|
||||||
|
transaction.validate(sumCache);
|
||||||
|
|
||||||
|
// Compose the string with values, sum, and validation result.
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
int calcSum = 0;
|
||||||
|
for (ICache<Integer> valueCache : valueCaches) {
|
||||||
|
if (result.length() != 0) result.append(" + ");
|
||||||
|
result.append(valueCache.getData());
|
||||||
|
calcSum += valueCache.getData();
|
||||||
|
}
|
||||||
|
result.append(" = ");
|
||||||
|
result.append(sumCache.getData());
|
||||||
|
if (calcSum != sumCache.getData()) {
|
||||||
|
result.append(" !INCORRECT! ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class for data item requests. This class holds the index
|
||||||
|
* argument so it can be examined when canceling stale requests.
|
||||||
|
*/
|
||||||
|
private class ValueRequestMonitor extends DataRequestMonitor<String> {
|
||||||
|
/** Index is used when canceling stale requests. */
|
||||||
|
int fIndex;
|
||||||
|
|
||||||
|
ValueRequestMonitor(int index) {
|
||||||
|
super(fDisplayExecutor, null);
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleRejectedExecutionException() {
|
||||||
|
// Shutting down, ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels any outstanding value requests for items which are no longer
|
||||||
|
* visible in the viewer.
|
||||||
|
*
|
||||||
|
* @param topIdx Index of top visible item in viewer.
|
||||||
|
* @param botIdx Index of bottom visible item in viewer.
|
||||||
|
*/
|
||||||
|
private void cancelStaleRequests(int topIdx, int botIdx) {
|
||||||
|
// Decrement the count of outstanding cancel calls.
|
||||||
|
fCancelCallsPending--;
|
||||||
|
|
||||||
|
// Must check again, in case disposed while re-dispatching.
|
||||||
|
if (fDataGeneratorCMs == null || fViewer.getTable().isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through the outstanding requests and cancel any that
|
||||||
|
// are not visible anymore.
|
||||||
|
for (Iterator<ValueRequestMonitor> itr =
|
||||||
|
fItemDataRequestMonitors.iterator(); itr.hasNext();)
|
||||||
|
{
|
||||||
|
ValueRequestMonitor item = itr.next();
|
||||||
|
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
||||||
|
// Set the item to canceled status, so that the data provider
|
||||||
|
// will ignore it.
|
||||||
|
item.cancel();
|
||||||
|
|
||||||
|
// Add the item index to list of indexes that were canceled,
|
||||||
|
// which will be sent to the table widget.
|
||||||
|
fIndexesToCancel.add(item.fIndex);
|
||||||
|
|
||||||
|
// Remove the item from the outstanding cancel requests.
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
||||||
|
Set<Integer> canceledIdxs = fIndexesToCancel;
|
||||||
|
fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
|
||||||
|
// Clear the indexes of the canceled request, so that the
|
||||||
|
// viewer knows to request them again when needed.
|
||||||
|
// Note: clearing using TableViewer.clear(int) seems very
|
||||||
|
// inefficient, it's better to use Table.clear(int[]).
|
||||||
|
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (Integer index : canceledIdxs) {
|
||||||
|
canceledIdxsArray[i++] = index;
|
||||||
|
}
|
||||||
|
fViewer.getTable().clear(canceledIdxsArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entry point for the example.
|
||||||
|
* @param args Program arguments.
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Create the shell to hold the viewer.
|
||||||
|
Display display = new Display();
|
||||||
|
Shell shell = new Shell(display, SWT.SHELL_TRIM);
|
||||||
|
shell.setLayout(new GridLayout());
|
||||||
|
GridData data = new GridData(GridData.FILL_BOTH);
|
||||||
|
shell.setLayoutData(data);
|
||||||
|
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
||||||
|
|
||||||
|
// Create the table viewer.
|
||||||
|
TableViewer tableViewer =
|
||||||
|
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
||||||
|
tableViewer.getControl().setLayoutData(data);
|
||||||
|
|
||||||
|
DsfExecutor executor = new DefaultDsfExecutor("Example executor");
|
||||||
|
|
||||||
|
// Create the data generator.
|
||||||
|
final IDataGenerator[] generators = new IDataGenerator[5];
|
||||||
|
for (int i = 0; i < generators.length; i++) {
|
||||||
|
generators[i] = new DataGeneratorWithExecutor(executor);
|
||||||
|
}
|
||||||
|
final IDataGenerator sumGenerator =
|
||||||
|
new ACPMSumDataGenerator(executor, generators);
|
||||||
|
|
||||||
|
// Create the content provider which will populate the viewer.
|
||||||
|
ACPMSumDataViewer contentProvider = new ACPMSumDataViewer(
|
||||||
|
tableViewer, new ImmediateInDsfExecutor(executor),
|
||||||
|
generators, sumGenerator);
|
||||||
|
tableViewer.setContentProvider(contentProvider);
|
||||||
|
tableViewer.setInput(new Object());
|
||||||
|
|
||||||
|
// Open the shell and service the display dispatch loop until user
|
||||||
|
// closes the shell.
|
||||||
|
shell.open();
|
||||||
|
while (!shell.isDisposed()) {
|
||||||
|
if (!display.readAndDispatch())
|
||||||
|
display.sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
||||||
|
// using a query again in order to wait for its completion.
|
||||||
|
Query<Object> shutdownQuery = new Query<Object>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<Object> rm) {
|
||||||
|
CountingRequestMonitor crm = new CountingRequestMonitor(
|
||||||
|
ImmediateExecutor.getInstance(), rm);
|
||||||
|
for (int i = 0; i < generators.length; i++) {
|
||||||
|
generators[i].shutdown(crm);
|
||||||
|
}
|
||||||
|
sumGenerator.shutdown(crm);
|
||||||
|
crm.setDoneCount(generators.length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
executor.execute(shutdownQuery);
|
||||||
|
try {
|
||||||
|
shutdownQuery.get();
|
||||||
|
} catch (Exception e) {}
|
||||||
|
|
||||||
|
// Shut down the display.
|
||||||
|
font.dispose();
|
||||||
|
display.dispose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2006, 2009 Wind River Systems and others.
|
* Copyright (c) 2006, 2011 Wind River Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -66,13 +66,15 @@ public class AsyncDataViewer
|
||||||
final private IDataGenerator fDataGenerator;
|
final private IDataGenerator fDataGenerator;
|
||||||
|
|
||||||
// Fields used in request cancellation logic.
|
// Fields used in request cancellation logic.
|
||||||
private List<ValueDataRequestMonitor> fItemDataRequestMonitors = new LinkedList<ValueDataRequestMonitor>();
|
private List<ValueDataRequestMonitor> fItemDataRequestMonitors =
|
||||||
|
new LinkedList<ValueDataRequestMonitor>();
|
||||||
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
||||||
private int fCancelCallsPending = 0;
|
private int fCancelCallsPending = 0;
|
||||||
|
|
||||||
public AsyncDataViewer(TableViewer viewer, IDataGenerator generator) {
|
public AsyncDataViewer(TableViewer viewer, IDataGenerator generator) {
|
||||||
fViewer = viewer;
|
fViewer = viewer;
|
||||||
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(fViewer.getTable().getDisplay());
|
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
||||||
|
fViewer.getTable().getDisplay());
|
||||||
fDataGenerator = generator;
|
fDataGenerator = generator;
|
||||||
fDataGenerator.addListener(this);
|
fDataGenerator.addListener(this);
|
||||||
}
|
}
|
||||||
|
@ -104,10 +106,18 @@ public class AsyncDataViewer
|
||||||
1, TimeUnit.MILLISECONDS);
|
1, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the number of visible items based on the top item index and
|
||||||
|
* table bounds.
|
||||||
|
* @param top Index of top item.
|
||||||
|
* @return calculated number of items in viewer
|
||||||
|
*/
|
||||||
private int getVisibleItemCount(int top) {
|
private int getVisibleItemCount(int top) {
|
||||||
Table table = fViewer.getTable();
|
Table table = fViewer.getTable();
|
||||||
int itemCount = table.getItemCount();
|
int itemCount = table.getItemCount();
|
||||||
return Math.min((table.getBounds().height / table.getItemHeight()) + 2, itemCount - top);
|
return Math.min(
|
||||||
|
(table.getBounds().height / table.getItemHeight()) + 2,
|
||||||
|
itemCount - top);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
|
@ -131,7 +141,10 @@ public class AsyncDataViewer
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the up to date count. When a new count is set to viewer, the
|
||||||
|
* viewer will refresh all items as well.
|
||||||
|
*/
|
||||||
private void queryItemCount() {
|
private void queryItemCount() {
|
||||||
// Request count from data provider. When the count is returned, we
|
// Request count from data provider. When the count is returned, we
|
||||||
// have to re-dispatch into the display thread to avoid calling
|
// have to re-dispatch into the display thread to avoid calling
|
||||||
|
@ -150,13 +163,25 @@ public class AsyncDataViewer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Dedicated class for data item requests. This class holds the index
|
/**
|
||||||
// argument so it can be examined when canceling stale requests.
|
* Retrieves value of an element at given index. When complete the value
|
||||||
private class ValueDataRequestMonitor extends DataRequestMonitor<String> {
|
* is written to the viewer.
|
||||||
|
* @param index Index of value to retrieve.
|
||||||
|
*/
|
||||||
|
private void queryValue(final int index) {
|
||||||
|
ValueDataRequestMonitor rm = new ValueDataRequestMonitor(index);
|
||||||
|
fItemDataRequestMonitors.add(rm);
|
||||||
|
fDataGenerator.getValue(index, rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class for data item requests. This class holds the index
|
||||||
|
* argument so it can be examined when canceling stale requests.
|
||||||
|
*/
|
||||||
|
private class ValueDataRequestMonitor extends DataRequestMonitor<Integer> {
|
||||||
|
|
||||||
/** Index is used when canceling stale requests. */
|
/** Index is used when canceling stale requests. */
|
||||||
int fIndex;
|
int fIndex;
|
||||||
|
@ -170,7 +195,8 @@ public class AsyncDataViewer
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
fItemDataRequestMonitors.remove(this);
|
fItemDataRequestMonitors.remove(this);
|
||||||
|
|
||||||
// Check if the request completed successfully, otherwise ignore it.
|
// Check if the request completed successfully, otherwise ignore
|
||||||
|
// it.
|
||||||
if (isSuccess()) {
|
if (isSuccess()) {
|
||||||
if (!fViewer.getTable().isDisposed()) {
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
fViewer.replace(getData(), fIndex);
|
fViewer.replace(getData(), fIndex);
|
||||||
|
@ -178,12 +204,6 @@ public class AsyncDataViewer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void queryValue(final int index) {
|
|
||||||
ValueDataRequestMonitor rm = new ValueDataRequestMonitor(index);
|
|
||||||
fItemDataRequestMonitors.add(rm);
|
|
||||||
fDataGenerator.getValue(index, rm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelStaleRequests(int topIdx, int botIdx) {
|
private void cancelStaleRequests(int topIdx, int botIdx) {
|
||||||
// Decrement the count of outstanding cancel calls.
|
// Decrement the count of outstanding cancel calls.
|
||||||
|
@ -194,7 +214,10 @@ public class AsyncDataViewer
|
||||||
|
|
||||||
// Go through the outstanding requests and cancel any that
|
// Go through the outstanding requests and cancel any that
|
||||||
// are not visible anymore.
|
// are not visible anymore.
|
||||||
for (Iterator<ValueDataRequestMonitor> itr = fItemDataRequestMonitors.iterator(); itr.hasNext();) {
|
for (Iterator<ValueDataRequestMonitor> itr =
|
||||||
|
fItemDataRequestMonitors.iterator();
|
||||||
|
itr.hasNext();)
|
||||||
|
{
|
||||||
ValueDataRequestMonitor item = itr.next();
|
ValueDataRequestMonitor item = itr.next();
|
||||||
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
||||||
// Set the item to canceled status, so that the data provider
|
// Set the item to canceled status, so that the data provider
|
||||||
|
@ -237,14 +260,16 @@ public class AsyncDataViewer
|
||||||
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
||||||
|
|
||||||
// Create the table viewer.
|
// Create the table viewer.
|
||||||
TableViewer tableViewer = new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
TableViewer tableViewer =
|
||||||
|
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
||||||
tableViewer.getControl().setLayoutData(data);
|
tableViewer.getControl().setLayoutData(data);
|
||||||
|
|
||||||
// Create the data generator.
|
// Create the data generator.
|
||||||
final IDataGenerator generator = new DataGeneratorWithExecutor();
|
final IDataGenerator generator = new DataGeneratorWithExecutor();
|
||||||
|
|
||||||
// Create the content provider which will populate the viewer.
|
// Create the content provider which will populate the viewer.
|
||||||
AsyncDataViewer contentProvider = new AsyncDataViewer(tableViewer, generator);
|
AsyncDataViewer contentProvider =
|
||||||
|
new AsyncDataViewer(tableViewer, generator);
|
||||||
tableViewer.setContentProvider(contentProvider);
|
tableViewer.setContentProvider(contentProvider);
|
||||||
tableViewer.setInput(new Object());
|
tableViewer.setInput(new Object());
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
//#ifdef exercises
|
||||||
|
package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
|
//#else
|
||||||
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data generator which performs a sum computation on data retrieved from a
|
||||||
|
* number of other data generators. The data retrieval from other generators
|
||||||
|
* is performed in parallel and the result is calculated once all data is
|
||||||
|
* received.
|
||||||
|
* <p>
|
||||||
|
* This calculating generator does not listen to events from the data
|
||||||
|
* providers so it relies on the client to re-retrieve data as needed.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DSF executor used to serialize data access within this data generator.
|
||||||
|
*/
|
||||||
|
final private DsfExecutor fExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data generators to retrieve original data to perform calculations on.
|
||||||
|
*/
|
||||||
|
final private IDataGenerator[] fDataGenerators;
|
||||||
|
|
||||||
|
public AsyncSumDataGenerator(DsfExecutor executor,
|
||||||
|
IDataGenerator[] generators)
|
||||||
|
{
|
||||||
|
fExecutor = executor;
|
||||||
|
fDataGenerators = generators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getCount(final DataRequestMonitor<Integer> rm) {
|
||||||
|
// Artificially delay the retrieval of the sum data to simulate
|
||||||
|
// real processing time.
|
||||||
|
fExecutor.schedule( new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
doGetCount(rm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the actual count retrieval and calculation.
|
||||||
|
* @param rm Request monitor to complete with data.
|
||||||
|
*/
|
||||||
|
private void doGetCount(final DataRequestMonitor<Integer> rm) {
|
||||||
|
// Array to store counts retrieved asynchronously
|
||||||
|
final int[] counts = new int[fDataGenerators.length];
|
||||||
|
|
||||||
|
// Counting request monitor is called once all data is retrieved.
|
||||||
|
final CountingRequestMonitor crm =
|
||||||
|
new CountingRequestMonitor(fExecutor, rm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
// Pick the highest count value.
|
||||||
|
Arrays.sort(counts, 0, counts.length - 1);
|
||||||
|
int maxCount = counts[counts.length - 1];
|
||||||
|
rm.setData(maxCount);
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Each call to data generator fills in one value in array.
|
||||||
|
for (int i = 0; i < fDataGenerators.length; i++) {
|
||||||
|
final int finalI = i;
|
||||||
|
fDataGenerators[i].getCount(
|
||||||
|
new DataRequestMonitor<Integer>(
|
||||||
|
ImmediateExecutor.getInstance(), crm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
counts[finalI] = getData();
|
||||||
|
crm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
crm.setDoneCount(fDataGenerators.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getValue(final int index, final DataRequestMonitor<Integer> rm)
|
||||||
|
{
|
||||||
|
// Artificially delay the retrieval of the sum data to simulate
|
||||||
|
// real processing time.
|
||||||
|
fExecutor.schedule( new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
doGetValue(index, rm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the actual value retrieval and calculation.
|
||||||
|
* @param rm Request monitor to complete with data.
|
||||||
|
*/
|
||||||
|
private void doGetValue(int index, final DataRequestMonitor<Integer> rm) {
|
||||||
|
// Array to store counts retrieved asynchronously
|
||||||
|
final int[] values = new int[fDataGenerators.length];
|
||||||
|
|
||||||
|
// Counting request monitor is called once all data is retrieved.
|
||||||
|
final CountingRequestMonitor crm =
|
||||||
|
new CountingRequestMonitor(fExecutor, rm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
// Sum up values in array.
|
||||||
|
int sum = 0;
|
||||||
|
for (int value : values) {
|
||||||
|
sum += value;
|
||||||
|
}
|
||||||
|
rm.setData(sum);
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Each call to data generator fills in one value in array.
|
||||||
|
for (int i = 0; i < fDataGenerators.length; i++) {
|
||||||
|
final int finalI = i;
|
||||||
|
fDataGenerators[i].getValue(
|
||||||
|
index,
|
||||||
|
new DataRequestMonitor<Integer>(
|
||||||
|
ImmediateExecutor.getInstance(), crm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
values[finalI] = getData();
|
||||||
|
crm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
crm.setDoneCount(fDataGenerators.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown(RequestMonitor rm) {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(final Listener listener) {
|
||||||
|
// no events generated
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(Listener listener) {
|
||||||
|
// no events generated
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,410 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
//#ifdef exercises
|
||||||
|
package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
|
//#else
|
||||||
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
|
||||||
|
import org.eclipse.cdt.dsf.ui.concurrent.DisplayDsfExecutor;
|
||||||
|
import org.eclipse.jface.viewers.ILazyContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.TableViewer;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.graphics.Font;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data viewer based on a table, which reads data from multiple data
|
||||||
|
* providers using asynchronous methods and performs a compultation
|
||||||
|
* on the retrieved data.
|
||||||
|
* <p>
|
||||||
|
* This example builds on the {@link AsyncDataViewer} example and
|
||||||
|
* demonstrates the pitfalls of retrieving data from multiple sources
|
||||||
|
* asynchronously: The data is retrieved separate from a set of providers
|
||||||
|
* as well as from a data provider that sums the values from the other
|
||||||
|
* providers. The viewer then performs a check to ensure consistency of
|
||||||
|
* retrieved data. If the retrieved data is inconsistent an "INCORRECT"
|
||||||
|
* label is added in the viewer.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This viewer is updated periodically every 10 seconds, instead of being
|
||||||
|
* updated with every change in every data provider, which would overwhelm
|
||||||
|
* the viewer.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@ConfinedToDsfExecutor("fDisplayExecutor")
|
||||||
|
public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
|
{
|
||||||
|
/** View update frequency interval. */
|
||||||
|
final private static int UPDATE_INTERVAL = 10000;
|
||||||
|
|
||||||
|
/** Executor to use instead of Display.asyncExec(). **/
|
||||||
|
@ThreadSafe
|
||||||
|
final private DsfExecutor fDisplayExecutor;
|
||||||
|
|
||||||
|
// The viewer and generator that this content provider using.
|
||||||
|
final private TableViewer fViewer;
|
||||||
|
final private IDataGenerator[] fDataGenerators;
|
||||||
|
final private IDataGenerator fSumGenerator;
|
||||||
|
|
||||||
|
// Fields used in request cancellation logic.
|
||||||
|
private List<ValueCountingRequestMonitor> fItemDataRequestMonitors =
|
||||||
|
new LinkedList<ValueCountingRequestMonitor>();
|
||||||
|
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
private int fCancelCallsPending = 0;
|
||||||
|
private Future<?> fRefreshFuture;
|
||||||
|
|
||||||
|
public AsyncSumDataViewer(TableViewer viewer,
|
||||||
|
IDataGenerator[] generators, IDataGenerator sumGenerator)
|
||||||
|
{
|
||||||
|
fViewer = viewer;
|
||||||
|
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
||||||
|
fViewer.getTable().getDisplay());
|
||||||
|
fDataGenerators = generators;
|
||||||
|
fSumGenerator = sumGenerator;
|
||||||
|
|
||||||
|
// Schedule a task to refresh the viewer periodically.
|
||||||
|
fRefreshFuture = fDisplayExecutor.scheduleAtFixedRate(
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
queryItemCount();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
// Cancel the periodic task of refreshing the view.
|
||||||
|
fRefreshFuture.cancel(false);
|
||||||
|
|
||||||
|
// Cancel any outstanding data requests.
|
||||||
|
for (ValueCountingRequestMonitor rm : fItemDataRequestMonitors) {
|
||||||
|
rm.cancel();
|
||||||
|
}
|
||||||
|
fItemDataRequestMonitors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
|
||||||
|
// Set the initial count to the viewer after the input is set.
|
||||||
|
queryItemCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateElement(final int index) {
|
||||||
|
// Calculate the visible index range.
|
||||||
|
final int topIdx = fViewer.getTable().getTopIndex();
|
||||||
|
final int botIdx = topIdx + getVisibleItemCount(topIdx);
|
||||||
|
|
||||||
|
// Request the item for the given index.
|
||||||
|
queryValue(index);
|
||||||
|
|
||||||
|
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
||||||
|
// calls to be combined together improving performance of the viewer.
|
||||||
|
fCancelCallsPending++;
|
||||||
|
fDisplayExecutor.execute(
|
||||||
|
new Runnable() { public void run() {
|
||||||
|
cancelStaleRequests(topIdx, botIdx);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the number of visible items based on the top item index and
|
||||||
|
* table bounds.
|
||||||
|
* @param top Index of top item.
|
||||||
|
* @return calculated number of items in viewer
|
||||||
|
*/
|
||||||
|
private int getVisibleItemCount(int top) {
|
||||||
|
Table table = fViewer.getTable();
|
||||||
|
int itemCount = table.getItemCount();
|
||||||
|
return Math.min(
|
||||||
|
(table.getBounds().height / table.getItemHeight()) + 2,
|
||||||
|
itemCount - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the up to date count.
|
||||||
|
*/
|
||||||
|
private void queryItemCount() {
|
||||||
|
// Note:The count is retrieved from the sum generator only, the sum
|
||||||
|
// generator is responsible for calculating the count based on
|
||||||
|
// individual data providers' counts.
|
||||||
|
fIndexesToCancel.clear();
|
||||||
|
fSumGenerator.getCount(
|
||||||
|
new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
setCountToViewer(getData());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void handleRejectedExecutionException() {
|
||||||
|
// Shutting down, ignore.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the givne count to the viewer. This will cause the viewer will
|
||||||
|
* refresh all items' data as well.
|
||||||
|
* @param count New count to set to viewer.
|
||||||
|
*/
|
||||||
|
private void setCountToViewer(int count) {
|
||||||
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
|
fViewer.setItemCount(count);
|
||||||
|
fViewer.getTable().clearAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves value of an element at given index. When complete the value
|
||||||
|
* is written to the viewer.
|
||||||
|
* @param index Index of value to retrieve.
|
||||||
|
*/
|
||||||
|
private void queryValue(final int index) {
|
||||||
|
// Values retrieved asynchronously from providers are stored in local
|
||||||
|
// arrays.
|
||||||
|
final int[] values = new int[fDataGenerators.length];
|
||||||
|
final int[] sum = new int[1];
|
||||||
|
|
||||||
|
// Counting request monitor is invoked when the required number of
|
||||||
|
// value requests is completed.
|
||||||
|
final ValueCountingRequestMonitor crm =
|
||||||
|
new ValueCountingRequestMonitor(index)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
fItemDataRequestMonitors.remove(this);
|
||||||
|
|
||||||
|
// Check if the request completed successfully, otherwise
|
||||||
|
// ignore it.
|
||||||
|
if (isSuccess()) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
int calcSum = 0;
|
||||||
|
for (int value : values) {
|
||||||
|
if (result.length() != 0) result.append(" + ");
|
||||||
|
result.append(value);
|
||||||
|
calcSum += value;
|
||||||
|
}
|
||||||
|
result.append(" = ");
|
||||||
|
result.append(sum[0]);
|
||||||
|
if (calcSum != sum[0]) {
|
||||||
|
result.append(" !INCORRECT! ");
|
||||||
|
}
|
||||||
|
setValueToViewer(fIndex, result.toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Request data from each data generator.
|
||||||
|
for (int i = 0; i < fDataGenerators.length; i++) {
|
||||||
|
final int finalI = i;
|
||||||
|
fDataGenerators[i].getValue(
|
||||||
|
index,
|
||||||
|
// Use the display executor to construct the request monitor,
|
||||||
|
// this will cause the handleCompleted() method to be
|
||||||
|
// automatically called on the display thread.
|
||||||
|
new DataRequestMonitor<Integer>(
|
||||||
|
ImmediateExecutor.getInstance(), crm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
values[finalI] = getData();
|
||||||
|
crm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separately request data from the sum data generator.
|
||||||
|
fSumGenerator.getValue(
|
||||||
|
index,
|
||||||
|
new DataRequestMonitor<Integer>(
|
||||||
|
ImmediateExecutor.getInstance(), crm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
sum[0] = getData();
|
||||||
|
crm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
crm.setDoneCount(fDataGenerators.length + 1);
|
||||||
|
fItemDataRequestMonitors.add(crm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the view value to the viewer.
|
||||||
|
* <p>Note: This method must be called in the display thread. </p>
|
||||||
|
* @param index Index of value to set.
|
||||||
|
* @param value New value.
|
||||||
|
*/
|
||||||
|
private void setValueToViewer(int index, String value) {
|
||||||
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
|
fViewer.replace(value, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class for data item requests. This class holds the index
|
||||||
|
* argument so it can be examined when canceling stale requests.
|
||||||
|
*/
|
||||||
|
private class ValueCountingRequestMonitor extends CountingRequestMonitor {
|
||||||
|
/** Index is used when canceling stale requests. */
|
||||||
|
int fIndex;
|
||||||
|
|
||||||
|
ValueCountingRequestMonitor(int index) {
|
||||||
|
super(fDisplayExecutor, null);
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleRejectedExecutionException() {
|
||||||
|
// Shutting down, ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels any outstanding value requests for items which are no longer
|
||||||
|
* visible in the viewer.
|
||||||
|
*
|
||||||
|
* @param topIdx Index of top visible item in viewer.
|
||||||
|
* @param botIdx Index of bottom visible item in viewer.
|
||||||
|
*/
|
||||||
|
private void cancelStaleRequests(int topIdx, int botIdx) {
|
||||||
|
// Decrement the count of outstanding cancel calls.
|
||||||
|
fCancelCallsPending--;
|
||||||
|
|
||||||
|
// Must check again, in case disposed while re-dispatching.
|
||||||
|
if (fDataGenerators == null || fViewer.getTable().isDisposed()) return;
|
||||||
|
|
||||||
|
// Go through the outstanding requests and cancel any that
|
||||||
|
// are not visible anymore.
|
||||||
|
for (Iterator<ValueCountingRequestMonitor> itr =
|
||||||
|
fItemDataRequestMonitors.iterator(); itr.hasNext();)
|
||||||
|
{
|
||||||
|
ValueCountingRequestMonitor item = itr.next();
|
||||||
|
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
||||||
|
// Set the item to canceled status, so that the data provider
|
||||||
|
// will ignore it.
|
||||||
|
item.cancel();
|
||||||
|
|
||||||
|
// Add the item index to list of indexes that were canceled,
|
||||||
|
// which will be sent to the table widget.
|
||||||
|
fIndexesToCancel.add(item.fIndex);
|
||||||
|
|
||||||
|
// Remove the item from the outstanding cancel requests.
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
||||||
|
Set<Integer> canceledIdxs = fIndexesToCancel;
|
||||||
|
fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
|
||||||
|
// Clear the indexes of the canceled request, so that the
|
||||||
|
// viewer knows to request them again when needed.
|
||||||
|
// Note: clearing using TableViewer.clear(int) seems very
|
||||||
|
// inefficient, it's better to use Table.clear(int[]).
|
||||||
|
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (Integer index : canceledIdxs) {
|
||||||
|
canceledIdxsArray[i++] = index;
|
||||||
|
}
|
||||||
|
fViewer.getTable().clear(canceledIdxsArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entry point for the example.
|
||||||
|
* @param args Program arguments.
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Create the shell to hold the viewer.
|
||||||
|
Display display = new Display();
|
||||||
|
Shell shell = new Shell(display, SWT.SHELL_TRIM);
|
||||||
|
shell.setLayout(new GridLayout());
|
||||||
|
GridData data = new GridData(GridData.FILL_BOTH);
|
||||||
|
shell.setLayoutData(data);
|
||||||
|
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
||||||
|
|
||||||
|
// Create the table viewer.
|
||||||
|
TableViewer tableViewer =
|
||||||
|
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
||||||
|
tableViewer.getControl().setLayoutData(data);
|
||||||
|
|
||||||
|
// Single executor (and single thread) is used by all data generators,
|
||||||
|
// including the sum generator.
|
||||||
|
DsfExecutor executor = new DefaultDsfExecutor("Example executor");
|
||||||
|
|
||||||
|
// Create the data generator.
|
||||||
|
final IDataGenerator[] generators = new IDataGenerator[5];
|
||||||
|
for (int i = 0; i < generators.length; i++) {
|
||||||
|
generators[i] = new DataGeneratorWithExecutor(executor);
|
||||||
|
}
|
||||||
|
final IDataGenerator sumGenerator =
|
||||||
|
new AsyncSumDataGenerator(executor, generators);
|
||||||
|
|
||||||
|
// Create the content provider which will populate the viewer.
|
||||||
|
AsyncSumDataViewer contentProvider =
|
||||||
|
new AsyncSumDataViewer(tableViewer, generators, sumGenerator);
|
||||||
|
tableViewer.setContentProvider(contentProvider);
|
||||||
|
tableViewer.setInput(new Object());
|
||||||
|
|
||||||
|
// Open the shell and service the display dispatch loop until user
|
||||||
|
// closes the shell.
|
||||||
|
shell.open();
|
||||||
|
while (!shell.isDisposed()) {
|
||||||
|
if (!display.readAndDispatch())
|
||||||
|
display.sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
||||||
|
// using a query again in order to wait for its completion.
|
||||||
|
Query<Object> shutdownQuery = new Query<Object>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<Object> rm) {
|
||||||
|
CountingRequestMonitor crm = new CountingRequestMonitor(
|
||||||
|
ImmediateExecutor.getInstance(), rm);
|
||||||
|
for (int i = 0; i < generators.length; i++) {
|
||||||
|
generators[i].shutdown(crm);
|
||||||
|
}
|
||||||
|
sumGenerator.shutdown(crm);
|
||||||
|
crm.setDoneCount(generators.length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
executor.execute(shutdownQuery);
|
||||||
|
try {
|
||||||
|
shutdownQuery.get();
|
||||||
|
} catch (Exception e) {}
|
||||||
|
|
||||||
|
// Shut down the display.
|
||||||
|
font.dispose();
|
||||||
|
display.dispose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
//#ifdef exercises
|
||||||
|
package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
|
//#else
|
||||||
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ICache;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateInDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestCache;
|
||||||
|
import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper class for the {@link IDataGenerator} interface, which returns
|
||||||
|
* ACPM cache objects to use for data retrieval instead of calling
|
||||||
|
* {@link IDataGenerator} asynchronous methods directly.
|
||||||
|
*/
|
||||||
|
public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
|
|
||||||
|
/** Cache class for retrieving the data generator's count. */
|
||||||
|
private class CountCache extends RequestCache<Integer> {
|
||||||
|
|
||||||
|
public CountCache() {
|
||||||
|
super(fExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void retrieve(DataRequestMonitor<Integer> rm) {
|
||||||
|
fDataGenerator.getCount(rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the cache when the count is changed.
|
||||||
|
*/
|
||||||
|
public void countChanged() {
|
||||||
|
// Make sure that if clients are currently waiting for a count,
|
||||||
|
// they are notified of the update (their request monitors will be
|
||||||
|
// completed with an error). They shoudl then re-request data
|
||||||
|
// from provider again.
|
||||||
|
setAndReset(null, new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Count changed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cache class for retrieving the data generator's values. */
|
||||||
|
private class ValueCache extends RequestCache<Integer> {
|
||||||
|
private int fIndex;
|
||||||
|
|
||||||
|
public ValueCache(int index) {
|
||||||
|
super(fExecutor);
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void retrieve(org.eclipse.cdt.dsf.concurrent.DataRequestMonitor<Integer> rm) {
|
||||||
|
fDataGenerator.getValue(fIndex, rm);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CountCache#countChanged()
|
||||||
|
*/
|
||||||
|
public void valueChanged() {
|
||||||
|
setAndReset(null, new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Value changed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executor used to synchronize data access in this cache manager.
|
||||||
|
* It has to be the same executor that is used by the data generators in
|
||||||
|
* order to guarantee data consistency.
|
||||||
|
*/
|
||||||
|
private ImmediateInDsfExecutor fExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data generator that this cache manager is a wrapper for.
|
||||||
|
*/
|
||||||
|
private IDataGenerator fDataGenerator;
|
||||||
|
|
||||||
|
/** Cache for data generator's count */
|
||||||
|
private CountCache fCountCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of caches for retrieving values. Each value index has a separate
|
||||||
|
* cache value object.
|
||||||
|
*/
|
||||||
|
private Map<Integer, ValueCache> fValueCaches = new HashMap<Integer, ValueCache>();
|
||||||
|
|
||||||
|
public DataGeneratorCacheManager(ImmediateInDsfExecutor executor, IDataGenerator dataGenerator) {
|
||||||
|
fExecutor = executor;
|
||||||
|
fDataGenerator = dataGenerator;
|
||||||
|
fDataGenerator.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
fDataGenerator.removeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data generator that this cache manager wraps.
|
||||||
|
*/
|
||||||
|
public IDataGenerator getDataGenerator() {
|
||||||
|
return fDataGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cache for data generator count.
|
||||||
|
*/
|
||||||
|
public ICache<Integer> getCount() {
|
||||||
|
if (fCountCache == null) {
|
||||||
|
fCountCache = new CountCache();
|
||||||
|
}
|
||||||
|
return fCountCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cache for a value at given index.
|
||||||
|
*
|
||||||
|
* @param index Index of value to return.
|
||||||
|
* @return Cache object for given value.
|
||||||
|
*/
|
||||||
|
public ICache<Integer> getValue(int index) {
|
||||||
|
ValueCache value = fValueCaches.get(index);
|
||||||
|
if (value == null) {
|
||||||
|
value = new ValueCache(index);
|
||||||
|
fValueCaches.put(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void countChanged() {
|
||||||
|
// Reset the count cache and all the value caches.
|
||||||
|
if (fCountCache != null) {
|
||||||
|
fCountCache.countChanged();
|
||||||
|
}
|
||||||
|
for (ValueCache value : fValueCaches.values()) {
|
||||||
|
value.valueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void valuesChanged(Set<Integer> indexes) {
|
||||||
|
// Reset selected value caches.
|
||||||
|
for (Integer index : indexes) {
|
||||||
|
ValueCache value = fValueCaches.get(index);
|
||||||
|
if (value != null) {
|
||||||
|
value.valueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2006, 2009 Wind River Systems and others.
|
* Copyright (c) 2006, 2011 Wind River Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -14,14 +14,14 @@ package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashMap;
|
||||||
//#ifdef answers
|
//#ifdef answers
|
||||||
//#import java.util.Iterator;
|
//#import java.util.Iterator;
|
||||||
//#endif
|
//#endif
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Map;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -70,6 +70,16 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
|
|
||||||
Request(RequestMonitor rm) {
|
Request(RequestMonitor rm) {
|
||||||
fRequestMonitor = rm;
|
fRequestMonitor = rm;
|
||||||
|
|
||||||
|
rm.addCancelListener(new RequestMonitor.ICanceledListener() {
|
||||||
|
public void requestCanceled(RequestMonitor rm) {
|
||||||
|
fExecutor.execute(new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
fQueue.remove(Request.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +103,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//#endif
|
//#endif
|
||||||
class ItemRequest extends Request {
|
class ItemRequest extends Request {
|
||||||
final int fIndex;
|
final int fIndex;
|
||||||
ItemRequest(int index, DataRequestMonitor<String> rm) {
|
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
|
||||||
super(rm);
|
super(rm);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
|
@ -156,24 +166,20 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private Set<Integer> fChangedIndexes = new HashSet<Integer>();
|
private Map<Integer, Integer> fChangedValues =
|
||||||
|
new HashMap<Integer, Integer>();
|
||||||
|
|
||||||
// Flag used to ensure that requests are processed sequentially.
|
|
||||||
//#ifdef exercises
|
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
|
||||||
// indicating allowed thread access to this class/method/member
|
|
||||||
//#else
|
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
|
||||||
//#endif
|
|
||||||
private boolean fServiceQueueInProgress = false;
|
|
||||||
|
|
||||||
//#ifdef exercises
|
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
|
||||||
// indicating allowed thread access to this class/method/member
|
|
||||||
//#endif
|
|
||||||
public DataGeneratorWithExecutor() {
|
public DataGeneratorWithExecutor() {
|
||||||
// Create the executor
|
// Create the executor
|
||||||
fExecutor = new DefaultDsfExecutor("Supplier Executor");
|
this(new DefaultDsfExecutor("Supplier Executor"));
|
||||||
|
}
|
||||||
|
//#ifdef exercises
|
||||||
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
|
// indicating allowed thread access to this class/method/member
|
||||||
|
//#endif
|
||||||
|
public DataGeneratorWithExecutor(DsfExecutor executor) {
|
||||||
|
// Create the executor
|
||||||
|
fExecutor = executor;
|
||||||
|
|
||||||
// Schedule a runnable to make the random changes.
|
// Schedule a runnable to make the random changes.
|
||||||
fExecutor.scheduleAtFixedRate(
|
fExecutor.scheduleAtFixedRate(
|
||||||
|
@ -182,8 +188,8 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
randomChanges();
|
randomChanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RANDOM_CHANGE_INTERVAL,
|
new Random().nextInt() % RANDOM_CHANGE_INTERVAL,
|
||||||
RANDOM_CHANGE_INTERVAL,
|
RANDOM_CHANGE_INTERVAL, //Add a 10% variance to the interval.
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +203,9 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
public void run() {
|
public void run() {
|
||||||
// Empty the queue of requests and fail them.
|
// Empty the queue of requests and fail them.
|
||||||
for (Request request : fQueue) {
|
for (Request request : fQueue) {
|
||||||
request.fRequestMonitor.setStatus(
|
request.fRequestMonitor.setStatus(new Status(
|
||||||
new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
request.fRequestMonitor.done();
|
request.fRequestMonitor.done();
|
||||||
}
|
}
|
||||||
fQueue.clear();
|
fQueue.clear();
|
||||||
|
@ -209,7 +216,8 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +235,9 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
rm.setStatus(new Status(
|
||||||
|
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +246,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
public void getValue(final int index, final DataRequestMonitor<String> rm) {
|
public void getValue(final int index, final DataRequestMonitor<Integer> rm) {
|
||||||
try {
|
try {
|
||||||
fExecutor.execute( new DsfRunnable() {
|
fExecutor.execute( new DsfRunnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -245,7 +255,8 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,7 +297,16 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private void serviceQueue() {
|
private void serviceQueue() {
|
||||||
|
fExecutor.schedule(
|
||||||
|
new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
doServiceQueue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doServiceQueue() {
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 3 - Add logic to discard cancelled requests from queue.
|
// TODO Exercise 3 - Add logic to discard cancelled requests from queue.
|
||||||
// Hint: Since serviceQueue() is called using the executor, and the
|
// Hint: Since serviceQueue() is called using the executor, and the
|
||||||
|
@ -305,33 +325,16 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//# }
|
//# }
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
// If a queue servicing is already scheduled, do nothing.
|
while (fQueue.size() != 0) {
|
||||||
if (fServiceQueueInProgress) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fQueue.size() != 0) {
|
|
||||||
// If there are requests to service, remove one from the queue and
|
// If there are requests to service, remove one from the queue and
|
||||||
// schedule a runnable to process the request after a processing
|
// schedule a runnable to process the request after a processing
|
||||||
// delay.
|
// delay.
|
||||||
fServiceQueueInProgress = true;
|
Request request = fQueue.remove(0);
|
||||||
final Request request = fQueue.remove(0);
|
if (request instanceof CountRequest) {
|
||||||
fExecutor.schedule(
|
processCountRequest((CountRequest)request);
|
||||||
new DsfRunnable() {
|
} else if (request instanceof ItemRequest) {
|
||||||
public void run() {
|
processItemRequest((ItemRequest)request);
|
||||||
if (request instanceof CountRequest) {
|
}
|
||||||
processCountRequest((CountRequest)request);
|
|
||||||
} else if (request instanceof ItemRequest) {
|
|
||||||
processItemRequest((ItemRequest)request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the processing flag and process next
|
|
||||||
// request.
|
|
||||||
fServiceQueueInProgress = false;
|
|
||||||
serviceQueue();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +346,8 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//#endif
|
//#endif
|
||||||
private void processCountRequest(CountRequest request) {
|
private void processCountRequest(CountRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<Integer> rm = (DataRequestMonitor<Integer>)request.fRequestMonitor;
|
DataRequestMonitor<Integer> rm =
|
||||||
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
rm.setData(fCount);
|
rm.setData(fCount);
|
||||||
rm.done();
|
rm.done();
|
||||||
|
@ -357,12 +361,13 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//#endif
|
//#endif
|
||||||
private void processItemRequest(ItemRequest request) {
|
private void processItemRequest(ItemRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<String> rm = (DataRequestMonitor<String>)request.fRequestMonitor;
|
DataRequestMonitor<Integer> rm =
|
||||||
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
if (fChangedIndexes.contains(request.fIndex)) {
|
if (fChangedValues.containsKey(request.fIndex)) {
|
||||||
rm.setData("Changed: " + request.fIndex);
|
rm.setData(fChangedValues.get(request.fIndex));
|
||||||
} else {
|
} else {
|
||||||
rm.setData(Integer.toString(request.fIndex));
|
rm.setData(request.fIndex);
|
||||||
}
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
@ -398,10 +403,11 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
private void randomCountReset() {
|
private void randomCountReset() {
|
||||||
// Calculate the new count.
|
// Calculate the new count.
|
||||||
Random random = new java.util.Random();
|
Random random = new java.util.Random();
|
||||||
fCount = MIN_COUNT + Math.abs(random.nextInt()) % (MAX_COUNT - MIN_COUNT);
|
fCount = MIN_COUNT +
|
||||||
|
Math.abs(random.nextInt()) % (MAX_COUNT - MIN_COUNT);
|
||||||
|
|
||||||
// Reset the changed values.
|
// Reset the changed values.
|
||||||
fChangedIndexes.clear();
|
fChangedValues.clear();
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Listener listener : fListeners) {
|
for (Listener listener : fListeners) {
|
||||||
|
@ -421,17 +427,19 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
private void randomDataChange() {
|
private void randomDataChange() {
|
||||||
// Calculate the indexes to change.
|
// Calculate the indexes to change.
|
||||||
Random random = new java.util.Random();
|
Random random = new java.util.Random();
|
||||||
Set<Integer> set = new HashSet<Integer>();
|
Map<Integer, Integer> changed = new HashMap<Integer, Integer>();
|
||||||
for (int i = 0; i < fCount * RANDOM_CHANGE_SET_PERCENTAGE / 100; i++) {
|
for (int i = 0; i < fCount * RANDOM_CHANGE_SET_PERCENTAGE / 100; i++) {
|
||||||
set.add( new Integer(Math.abs(random.nextInt()) % fCount) );
|
int randomIndex = Math.abs(random.nextInt()) % fCount;
|
||||||
}
|
int randomValue = Math.abs(random.nextInt()) % fCount;
|
||||||
|
changed.put(randomIndex, randomValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the indexes to an overall set of changed indexes.
|
// Add the indexes to an overall set of changed indexes.
|
||||||
fChangedIndexes.addAll(set);
|
fChangedValues.putAll(changed);
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Listener listener : fListeners) {
|
for (Object listener : fListeners) {
|
||||||
listener.valuesChanged(set);
|
((Listener)listener).valuesChanged(changed.keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2006, 2009 Wind River Systems and others.
|
* Copyright (c) 2006, 2011 Wind River Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -15,9 +15,9 @@ package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Map;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -41,7 +41,9 @@ import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
|
||||||
* synchronization.
|
* synchronization.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
public class DataGeneratorWithThread extends Thread
|
||||||
|
implements IDataGenerator
|
||||||
|
{
|
||||||
|
|
||||||
// Request objects are used to serialize the interface calls into objects
|
// Request objects are used to serialize the interface calls into objects
|
||||||
// which can then be pushed into a queue.
|
// which can then be pushed into a queue.
|
||||||
|
@ -61,7 +63,7 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
|
|
||||||
class ItemRequest extends Request {
|
class ItemRequest extends Request {
|
||||||
final int fIndex;
|
final int fIndex;
|
||||||
ItemRequest(int index, DataRequestMonitor<String> rm) {
|
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
|
||||||
super(rm);
|
super(rm);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +78,8 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
// Main request queue of the data generator. The getValue(), getCount(),
|
// Main request queue of the data generator. The getValue(), getCount(),
|
||||||
// and shutdown() methods write into the queue, while the run() method
|
// and shutdown() methods write into the queue, while the run() method
|
||||||
// reads from it.
|
// reads from it.
|
||||||
private final BlockingQueue<Request> fQueue = new LinkedBlockingQueue<Request>();
|
private final BlockingQueue<Request> fQueue =
|
||||||
|
new LinkedBlockingQueue<Request>();
|
||||||
|
|
||||||
// ListenerList class provides thread safety.
|
// ListenerList class provides thread safety.
|
||||||
private ListenerList fListeners = new ListenerList();
|
private ListenerList fListeners = new ListenerList();
|
||||||
|
@ -88,7 +91,8 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
private int fCountResetTrigger = 0;
|
private int fCountResetTrigger = 0;
|
||||||
|
|
||||||
// Elements which were modified since the last reset.
|
// Elements which were modified since the last reset.
|
||||||
private Set<Integer> fChangedIndexes = Collections.synchronizedSet(new HashSet<Integer>());
|
private Map<Integer, Integer> fChangedValues =
|
||||||
|
Collections.synchronizedMap(new HashMap<Integer, Integer>());
|
||||||
|
|
||||||
// Used to determine when to make changes in data.
|
// Used to determine when to make changes in data.
|
||||||
private long fLastChangeTime = System.currentTimeMillis();
|
private long fLastChangeTime = System.currentTimeMillis();
|
||||||
|
@ -108,7 +112,8 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
fQueue.add(new ShutdownRequest(rm));
|
fQueue.add(new ShutdownRequest(rm));
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,16 +122,18 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
if (!fShutdown.get()) {
|
if (!fShutdown.get()) {
|
||||||
fQueue.add(new CountRequest(rm));
|
fQueue.add(new CountRequest(rm));
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getValue(int index, DataRequestMonitor<String> rm) {
|
public void getValue(int index, DataRequestMonitor<Integer> rm) {
|
||||||
if (!fShutdown.get()) {
|
if (!fShutdown.get()) {
|
||||||
fQueue.add(new ItemRequest(index, rm));
|
fQueue.add(new ItemRequest(index, rm));
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +157,6 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
// If a request was dequeued, process it.
|
// If a request was dequeued, process it.
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
// Simulate a processing delay.
|
// Simulate a processing delay.
|
||||||
Thread.sleep(PROCESSING_DELAY);
|
|
||||||
|
|
||||||
if (request instanceof CountRequest) {
|
if (request instanceof CountRequest) {
|
||||||
processCountRequest((CountRequest)request);
|
processCountRequest((CountRequest)request);
|
||||||
|
@ -162,6 +168,8 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
request.fRequestMonitor.done();
|
request.fRequestMonitor.done();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Thread.sleep(PROCESSING_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate data changes.
|
// Simulate data changes.
|
||||||
|
@ -173,7 +181,8 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
|
|
||||||
private void processCountRequest(CountRequest request) {
|
private void processCountRequest(CountRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<Integer> rm = (DataRequestMonitor<Integer>)request.fRequestMonitor;
|
DataRequestMonitor<Integer> rm =
|
||||||
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
rm.setData(fCount);
|
rm.setData(fCount);
|
||||||
rm.done();
|
rm.done();
|
||||||
|
@ -181,12 +190,13 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
|
|
||||||
private void processItemRequest(ItemRequest request) {
|
private void processItemRequest(ItemRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<String> rm = (DataRequestMonitor<String>)request.fRequestMonitor;
|
DataRequestMonitor<Integer> rm =
|
||||||
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
if (fChangedIndexes.contains(request.fIndex)) {
|
if (fChangedValues.containsKey(request.fIndex)) {
|
||||||
rm.setData("Changed: " + request.fIndex);
|
rm.setData(fChangedValues.get(request.fIndex));
|
||||||
} else {
|
} else {
|
||||||
rm.setData(Integer.toString(request.fIndex));
|
rm.setData(request.fIndex);
|
||||||
}
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
@ -194,12 +204,14 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
|
|
||||||
private void randomChanges() {
|
private void randomChanges() {
|
||||||
// Check if enough time is elapsed.
|
// Check if enough time is elapsed.
|
||||||
if (System.currentTimeMillis() > fLastChangeTime + RANDOM_CHANGE_INTERVAL) {
|
if (System.currentTimeMillis() >
|
||||||
|
fLastChangeTime + RANDOM_CHANGE_INTERVAL)
|
||||||
|
{
|
||||||
fLastChangeTime = System.currentTimeMillis();
|
fLastChangeTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Once every number of changes, reset the count, the rest of the
|
// Once every number of changes, reset the count, the rest of the
|
||||||
// times just change certain values.
|
// times just change certain values.
|
||||||
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0){
|
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0) {
|
||||||
randomCountReset();
|
randomCountReset();
|
||||||
} else {
|
} else {
|
||||||
randomDataChange();
|
randomDataChange();
|
||||||
|
@ -213,7 +225,7 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
fCount = MIN_COUNT + Math.abs(random.nextInt()) % (MAX_COUNT - MIN_COUNT);
|
fCount = MIN_COUNT + Math.abs(random.nextInt()) % (MAX_COUNT - MIN_COUNT);
|
||||||
|
|
||||||
// Reset the changed values.
|
// Reset the changed values.
|
||||||
fChangedIndexes.clear();
|
fChangedValues.clear();
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Object listener : fListeners.getListeners()) {
|
for (Object listener : fListeners.getListeners()) {
|
||||||
|
@ -224,17 +236,19 @@ public class DataGeneratorWithThread extends Thread implements IDataGenerator {
|
||||||
private void randomDataChange() {
|
private void randomDataChange() {
|
||||||
// Calculate the indexes to change.
|
// Calculate the indexes to change.
|
||||||
Random random = new java.util.Random();
|
Random random = new java.util.Random();
|
||||||
Set<Integer> set = new HashSet<Integer>();
|
Map<Integer, Integer> changed = new HashMap<Integer, Integer>();
|
||||||
for (int i = 0; i < fCount * RANDOM_CHANGE_SET_PERCENTAGE / 100; i++) {
|
for (int i = 0; i < fCount * RANDOM_CHANGE_SET_PERCENTAGE / 100; i++) {
|
||||||
set.add( new Integer(Math.abs(random.nextInt()) % fCount) );
|
int randomIndex = Math.abs(random.nextInt()) % fCount;
|
||||||
|
int randomValue = Math.abs(random.nextInt()) % fCount;
|
||||||
|
changed.put(randomIndex, randomValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the indexes to an overall set of changed indexes.
|
// Add the indexes to an overall set of changed indexes.
|
||||||
fChangedIndexes.addAll(set);
|
fChangedValues.putAll(changed);
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Object listener : fListeners.getListeners()) {
|
for (Object listener : fListeners.getListeners()) {
|
||||||
((Listener)listener).valuesChanged(set);
|
((Listener)listener).valuesChanged(changed.keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2006, 2009 Wind River Systems and others.
|
* Copyright (c) 2006, 2011 Wind River Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -41,11 +41,11 @@ public interface IDataGenerator {
|
||||||
// Changing the count range can stress the scalability of the system, while
|
// Changing the count range can stress the scalability of the system, while
|
||||||
// changing of the process delay and random change interval can stress
|
// changing of the process delay and random change interval can stress
|
||||||
// its performance.
|
// its performance.
|
||||||
final static int MIN_COUNT = 100;
|
final static int MIN_COUNT = 50;
|
||||||
final static int MAX_COUNT = 200;
|
final static int MAX_COUNT = 100;
|
||||||
final static int PROCESSING_DELAY = 10;
|
final static int PROCESSING_DELAY = 500;
|
||||||
final static int RANDOM_CHANGE_INTERVAL = 10000;
|
final static int RANDOM_CHANGE_INTERVAL = 4000;
|
||||||
final static int RANDOM_COUNT_CHANGE_INTERVALS = 3;
|
final static int RANDOM_COUNT_CHANGE_INTERVALS = 5;
|
||||||
final static int RANDOM_CHANGE_SET_PERCENTAGE = 10;
|
final static int RANDOM_CHANGE_SET_PERCENTAGE = 10;
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ public interface IDataGenerator {
|
||||||
|
|
||||||
// Data access methods.
|
// Data access methods.
|
||||||
void getCount(DataRequestMonitor<Integer> rm);
|
void getCount(DataRequestMonitor<Integer> rm);
|
||||||
void getValue(int index, DataRequestMonitor<String> rm);
|
void getValue(int index, DataRequestMonitor<Integer> rm);
|
||||||
|
|
||||||
// Method used to shutdown the data generator including any threads that
|
// Method used to shutdown the data generator including any threads that
|
||||||
// it may use.
|
// it may use.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Wind River Systems and others.
|
* Copyright (c) 2008, 2011 Wind River Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -14,8 +14,11 @@ package org.eclipse.cdt.examples.dsf.dataviewer;
|
||||||
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
//#package org.eclipse.cdt.examples.dsf.dataviewer.answers;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Query;
|
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||||
|
@ -35,8 +38,8 @@ import org.eclipse.swt.widgets.Shell;
|
||||||
* This viewer implements the {@link IStructuredContentProvider} interface
|
* This viewer implements the {@link IStructuredContentProvider} interface
|
||||||
* which is used by the JFace TableViewer class to populate a Table. This
|
* which is used by the JFace TableViewer class to populate a Table. This
|
||||||
* interface contains one principal methods for reading data {@link #getElements(Object)},
|
* interface contains one principal methods for reading data {@link #getElements(Object)},
|
||||||
* which synchronously returns an array of elements. In order to implement this
|
* which synchronously returns an array of elements. In order to implement
|
||||||
* method using the asynchronous data generator, this provider uses the
|
* this method using the asynchronous data generator, this provider uses the
|
||||||
* {@link Query} object.
|
* {@link Query} object.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
|
@ -84,27 +87,43 @@ public class SyncDataViewer
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the array that will be filled with elements.
|
final int finalCount = count;
|
||||||
// For each index in the array execute a query to get the element at
|
Query<List<Integer>> valueQuery = new Query<List<Integer>>() {
|
||||||
// that index.
|
@Override
|
||||||
final Object[] elements = new Object[count];
|
protected void execute(final DataRequestMonitor<List<Integer>> rm) {
|
||||||
|
final Integer[] retVal = new Integer[finalCount];
|
||||||
for (int i = 0; i < count; i++) {
|
final CountingRequestMonitor crm = new CountingRequestMonitor(
|
||||||
final int index = i;
|
ImmediateExecutor.getInstance(), rm)
|
||||||
Query<String> valueQuery = new Query<String>() {
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void execute(DataRequestMonitor<String> rm) {
|
protected void handleSuccess() {
|
||||||
fDataGenerator.getValue(index, rm);
|
rm.setData(Arrays.asList(retVal));
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for (int i = 0; i < finalCount; i++) {
|
||||||
|
final int finalI = i;
|
||||||
|
fDataGenerator.getValue(
|
||||||
|
i,
|
||||||
|
new DataRequestMonitor<Integer>(
|
||||||
|
ImmediateExecutor.getInstance(), crm)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
retVal[finalI] = getData();
|
||||||
|
crm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
crm.setDoneCount(finalCount);
|
||||||
ImmediateExecutor.getInstance().execute(valueQuery);
|
}
|
||||||
try {
|
};
|
||||||
elements[i] = valueQuery.get();
|
ImmediateExecutor.getInstance().execute(valueQuery);
|
||||||
} catch (Exception e) {
|
try {
|
||||||
elements[i] = "error";
|
return valueQuery.get().toArray(new Integer[0]);
|
||||||
}
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
return elements;
|
return new Object[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
@ -140,6 +159,10 @@ public class SyncDataViewer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entry point for the example.
|
||||||
|
* @param args Program arguments.
|
||||||
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Create the shell to hold the viewer.
|
// Create the shell to hold the viewer.
|
||||||
Display display = new Display();
|
Display display = new Display();
|
||||||
|
@ -162,7 +185,8 @@ public class SyncDataViewer
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
// Create the content provider which will populate the viewer.
|
// Create the content provider which will populate the viewer.
|
||||||
SyncDataViewer contentProvider = new SyncDataViewer(tableViewer, generator);
|
SyncDataViewer contentProvider =
|
||||||
|
new SyncDataViewer(tableViewer, generator);
|
||||||
tableViewer.setContentProvider(contentProvider);
|
tableViewer.setContentProvider(contentProvider);
|
||||||
tableViewer.setInput(new Object());
|
tableViewer.setInput(new Object());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue