1
0
Fork 0
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:
Andrew Gvozdev 2011-12-08 16:40:00 -05:00
commit 0df3dfbbbc
55 changed files with 2627 additions and 679 deletions

View file

@ -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;
} }

View file

@ -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; }
}
}
}

View file

@ -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();

View file

@ -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};
}
} }
} }

View file

@ -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);
} }
} }
} }

View file

@ -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);
} }

View file

@ -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());

View file

@ -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 */

View file

@ -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);
} }

View file

@ -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();
// }; // };

View file

@ -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();
}
} }

View file

@ -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);
// }; // };

View file

@ -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);
}
} }

View file

@ -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$

View file

@ -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;

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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;

View file

@ -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();

View file

@ -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;
} }
} }

View file

@ -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;

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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) {

View file

@ -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;
} }

View file

@ -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

View file

@ -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) {

View file

@ -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;
} }
} }

View file

@ -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();

View file

@ -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();
}}); }});

View file

@ -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;

View file

@ -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();

View file

@ -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);
// //

View file

@ -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;
} }

View 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&lt;?&gt;[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
</resource>
</component>

View file

@ -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();
}
} }

View file

@ -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 ++;

View file

@ -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();
}
} }

View file

@ -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++;

View file

@ -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) {}
}
}

View file

@ -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();
}
}

View file

@ -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());

View file

@ -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
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}
}
}

View file

@ -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());
} }
} }
} }

View file

@ -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());
} }
} }
} }

View file

@ -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.

View file

@ -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());