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

Bug 535256: Rewrite removes attributes, key and base from C++ enum

Fix and tests.

Change-Id: I1f5519f833563378d87b3c932b754e29c3e32b06
Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
Signed-off-by: Thomas Corbat <tcorbat@hsr.ch>
This commit is contained in:
Hansruedi Patzen 2018-05-29 13:21:41 +02:00 committed by Thomas Corbat
parent 4c66f7c8f3
commit bc4aa4597d
10 changed files with 178 additions and 10 deletions

View file

@ -55,6 +55,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
@ -1225,4 +1226,18 @@ public class ReplaceTests extends ChangeGeneratorTest {
public void testCopyReplaceAttribute_Bug535275() throws Exception {
compareCopyResult(new CopyReplaceVisitor(this, ICPPASTFunctionDeclarator.class::isInstance));
}
//enum [[foo]] X : int [[bar]] {
//};
public void testEnumReplacementRetainsAttributes_Bug535256_1() throws Exception {
compareCopyResult(new CopyReplaceVisitor(this, ICPPASTEnumerationSpecifier.class::isInstance));
}
//enum class EC {
//};
//enum struct ES {
//};
public void testScopedEnumReplacementRetains_Bug535256_2() throws Exception {
compareCopyResult(new CopyReplaceVisitor(this, ICPPASTEnumerationSpecifier.class::isInstance));
}
}

View file

@ -194,3 +194,23 @@ namespace [[foo]] FOO __attribute__((__visibility__("default")))
}
//!Attributed anonymous enum declaration
//%CPP
enum [[foo]] { };
//!Attributed named enum declaration
//%CPP
enum [[foo]] X{ };
//!Attributed anonymous enum with attributed base specifier
//%CPP
enum [[foo]] : int [[bar]] { };
//!Attributed scoped enum declaration with keyword struct
//%CPP
enum struct [[foo]] X{ };
//!Attributed scoped enum declaration with keyword class
//%CPP
enum class [[foo]] X{ };

View file

@ -24,6 +24,15 @@ public interface ICPPASTEnumerationSpecifier extends IASTEnumerationSpecifier, I
public static final ASTNodeProperty BASE_TYPE = new ASTNodeProperty(
"ICPPASTEnumerationSpecifier.BASE_TYPE [ICPPASTDeclSpecifier]"); //$NON-NLS-1$
/**
* @since 6.5
*/
public enum ScopeStyle {
CLASS,
STRUCT,
NONE
}
@Override
public ICPPASTEnumerationSpecifier copy();
@ -35,8 +44,23 @@ public interface ICPPASTEnumerationSpecifier extends IASTEnumerationSpecifier, I
/**
* Not allowed on frozen AST.
* @deprecated Use setScopeToken instead
* If {@code isScoped == true} is passed, the {@code ScopeToken.CLASS} scope token is assumed.
*/
@Deprecated
public void setIsScoped(boolean isScoped);
/**
* Not allowed on frozen AST.
* @since 6.5
*/
public void setScopeStyle(ScopeStyle scopeStyle);
/**
* @since 6.5
*/
public ScopeStyle getScopeStyle();
/**
* An enum is scoped if it uses the enumeration head {@code enum class} or {@code enum struct}.

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.IASTToken;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.INodeFactory;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier.ScopeStyle;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation.Operator;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTArrayRangeDesignator;
import org.eclipse.cdt.core.dom.parser.cpp.ICPPASTAttributeSpecifier;
@ -158,9 +159,17 @@ public interface ICPPNodeFactory extends INodeFactory {
/**
* @since 5.2
* @deprecated Use {@code newEnumerationSpecifier(ScopeToken, IASTName, ICPPASTDeclSpecifier)} instead.
* If {@code isScoped == true} is passed {@code ScopeToken.CLASS} is assumed.
*/
@Deprecated
public ICPPASTEnumerationSpecifier newEnumerationSpecifier(boolean isScoped, IASTName name, ICPPASTDeclSpecifier baseType);
/**
* @since 6.5
*/
public ICPPASTEnumerationSpecifier newEnumerationSpecifier(ScopeStyle scopeStyle, IASTName name, ICPPASTDeclSpecifier baseType);
public ICPPASTExplicitTemplateInstantiation newExplicitTemplateInstantiation(IASTDeclaration declaration);
@Override

View file

@ -26,7 +26,7 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTInternalEnumerationSpecifier
*/
public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier
implements IASTInternalEnumerationSpecifier, ICPPASTEnumerationSpecifier {
private boolean fIsScoped;
private ScopeStyle fScopeStyle;
private boolean fIsOpaque;
private IASTName fName;
private ICPPASTDeclSpecifier fBaseType;
@ -40,12 +40,18 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier
public CPPASTEnumerationSpecifier() {
}
@Deprecated
public CPPASTEnumerationSpecifier(boolean isScoped, IASTName name, ICPPASTDeclSpecifier baseType) {
fIsScoped= isScoped;
this(isScoped ? ScopeStyle.CLASS : ScopeStyle.NONE, name, baseType);
}
public CPPASTEnumerationSpecifier(ScopeStyle scopeStyle, IASTName name, ICPPASTDeclSpecifier baseType) {
setScopeStyle(scopeStyle);
setName(name);
setBaseType(baseType);
}
@Override
public CPPASTEnumerationSpecifier copy() {
return copy(CopyStyle.withoutLocations);
@ -53,7 +59,7 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier
@Override
public CPPASTEnumerationSpecifier copy(CopyStyle style) {
CPPASTEnumerationSpecifier copy = new CPPASTEnumerationSpecifier(fIsScoped,
CPPASTEnumerationSpecifier copy = new CPPASTEnumerationSpecifier(fScopeStyle,
fName == null ? null : fName.copy(style),
fBaseType == null ? null : fBaseType.copy(style));
copy.fIsOpaque = fIsOpaque;
@ -154,14 +160,25 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier
}
@Override
@Deprecated
public void setIsScoped(boolean isScoped) {
setScopeStyle(isScoped ? ScopeStyle.CLASS : ScopeStyle.NONE);
}
@Override
public void setScopeStyle(ScopeStyle scopeStyle) {
assertNotFrozen();
fIsScoped= isScoped;
fScopeStyle = scopeStyle;
}
@Override
public ScopeStyle getScopeStyle() {
return fScopeStyle;
}
@Override
public boolean isScoped() {
return fIsScoped;
return fScopeStyle != ScopeStyle.NONE;
}
@Override

View file

@ -78,6 +78,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier.ScopeStyle;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList;
@ -381,14 +382,21 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
}
@Override
@Deprecated
public ICPPASTEnumerationSpecifier newEnumerationSpecifier(boolean isScoped, IASTName name,
ICPPASTDeclSpecifier baseType) {
return new CPPASTEnumerationSpecifier(isScoped, name, baseType);
}
@Override
public ICPPASTEnumerationSpecifier newEnumerationSpecifier(ScopeStyle scopeStyle, IASTName name,
ICPPASTDeclSpecifier baseType) {
return new CPPASTEnumerationSpecifier(scopeStyle, name, baseType);
}
@Override
public ICPPASTEnumerationSpecifier newEnumerationSpecifier(IASTName name) {
return new CPPASTEnumerationSpecifier(false, name, null);
return new CPPASTEnumerationSpecifier(ScopeStyle.NONE, name, null);
}
@Override

View file

@ -95,6 +95,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier.ScopeStyle;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldDeclarator;
@ -3561,7 +3562,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
}
addAttributeSpecifiers(attributes, result);
attributesEndOffset(endOffset, attributes);
endOffset = attributesEndOffset(endOffset, attributes);
setRange(result, offset, endOffset);
} catch (BacktrackException e) {
if (returnToken != null) {
@ -3628,6 +3629,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
final int offset= consume(IToken.t_enum).getOffset();
int endOffset= 0;
boolean isScoped= false;
ScopeStyle scopeStyle = ScopeStyle.NONE;
IASTName name= null;
ICPPASTDeclSpecifier baseType= null;
List<IASTAttributeSpecifier> attributes = null;
@ -3635,7 +3637,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
try {
int lt1= LT(1);
if (lt1 == IToken.t_class || lt1 == IToken.t_struct) {
isScoped= true;
scopeStyle = (lt1 == IToken.t_class) ? ScopeStyle.CLASS : ScopeStyle.STRUCT;
isScoped = true;
consume();
}
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier
@ -3676,7 +3679,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
name= getNodeFactory().newName();
}
final ICPPASTEnumerationSpecifier result= getNodeFactory().newEnumerationSpecifier(isScoped, name, baseType);
final ICPPASTEnumerationSpecifier result= getNodeFactory().newEnumerationSpecifier(scopeStyle, name, baseType);
result.setIsOpaque(isOpaque);
if (lt1 == IToken.tLBRACE) {
endOffset= enumBody(result);

View file

@ -34,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.parser.GCCKeywords;
@ -225,8 +226,32 @@ public class DeclSpecWriter extends NodeWriter {
private void writeEnumSpec(IASTEnumerationSpecifier enumSpec) {
scribe.printStringSpace(Keywords.ENUM);
writeAttributes(enumSpec, EnumSet.of(SpaceLocation.AFTER));
boolean isCppEnum = enumSpec instanceof ICPPASTEnumerationSpecifier;
if (isCppEnum) {
ICPPASTEnumerationSpecifier cppEnumSpec = (ICPPASTEnumerationSpecifier) enumSpec;
if (cppEnumSpec.isScoped()) {
switch (cppEnumSpec.getScopeStyle()) {
case CLASS:
scribe.printStringSpace(Keywords.CLASS);
break;
case STRUCT:
scribe.printStringSpace(Keywords.STRUCT);
break;
default:
break;
}
}
writeAttributes(cppEnumSpec, EnumSet.of(SpaceLocation.AFTER));
}
enumSpec.getName().accept(visitor);
if (isCppEnum) {
ICPPASTDeclSpecifier baseType = ((ICPPASTEnumerationSpecifier) enumSpec).getBaseType();
if (baseType != null) {
scribe.print(SPACE_COLON_SPACE);
writeDelcSpec(baseType);
scribe.printSpace();
}
}
scribe.print('{');
scribe.printSpace();
IASTEnumerator[] enums = enumSpec.getEnumerators();

View file

@ -114,11 +114,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
@ -2059,6 +2061,19 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
name.accept(this);
}
ICPPASTEnumerationSpecifier cppNode = null;
if (node instanceof ICPPASTEnumerationSpecifier) {
cppNode = (ICPPASTEnumerationSpecifier) node;
formatLeadingAttributes(cppNode);
ICPPASTDeclSpecifier baseType = cppNode.getBaseType();
if (baseType != null) {
scribe.space();
scribe.printNextToken(Token.tCOLON);
scribe.space();
baseType.accept(this);
}
}
formatLeftCurlyBrace(line, preferences.brace_position_for_type_declaration);
formatOpeningBrace(preferences.brace_position_for_type_declaration, preferences.insert_space_before_opening_brace_in_type_declaration);
final int braceIndent= scribe.numberOfIndentations;

View file

@ -3538,4 +3538,36 @@ public class CodeFormatterTest extends BaseUITestCase {
public void testAttributedNamesapces_Bug535274() throws Exception {
assertFormatterResult();
}
//enum[[foo]]{};
//enum [[foo]] {
//};
public void testAttributedAnonymousEnumDeclaration_Bug535256_1() throws Exception {
assertFormatterResult();
}
//enum[[foo]] X{};
//enum [[foo]] X {
//};
public void testAttributedNamedEnumDeclaration_Bug535256_2() throws Exception {
assertFormatterResult();
}
//enum[[foo]]:int [[bar]]{};
//enum [[foo]] : int [[bar]] {
//};
public void testAttributedNamedEnumDeclarationWithAttributedBaseSpecifier_Bug535256_3() throws Exception {
assertFormatterResult();
}
//enum struct [[foo]] X{};
//enum struct [[foo]] X {
//};
public void testAttributedNamedScopedEnumDeclaration_Bug535256_4() throws Exception {
assertFormatterResult();
}
}