forked from qt-creator/qt-creator
Added protocol & class definedness checks, and added property attribute checks.
This commit is contained in:
@@ -51,6 +51,7 @@ void CheckUndefinedSymbols::setGlobalNamespaceBinding(NamespaceBindingPtr global
|
||||
{
|
||||
_globalNamespaceBinding = globalNamespaceBinding;
|
||||
_types.clear();
|
||||
_protocols.clear();
|
||||
|
||||
if (_globalNamespaceBinding) {
|
||||
QSet<NamespaceBinding *> processed;
|
||||
@@ -130,6 +131,20 @@ void CheckUndefinedSymbols::addType(Name *name)
|
||||
_types.insert(QByteArray(id->chars(), id->size()));
|
||||
}
|
||||
|
||||
void CheckUndefinedSymbols::addProtocol(Name *name)
|
||||
{
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
if (Identifier *id = name->identifier())
|
||||
_protocols.insert(QByteArray(id->chars(), id->size()));
|
||||
}
|
||||
|
||||
bool CheckUndefinedSymbols::isProtocol(const QByteArray &name) const
|
||||
{
|
||||
return _protocols.contains(name);
|
||||
}
|
||||
|
||||
void CheckUndefinedSymbols::buildTypeMap(Class *klass)
|
||||
{
|
||||
addType(klass->name());
|
||||
@@ -186,9 +201,9 @@ void CheckUndefinedSymbols::buildTypeMap(NamespaceBinding *binding, QSet<Namespa
|
||||
for (unsigned i = 0; i < klass->memberCount(); ++i)
|
||||
buildMemberTypeMap(klass->memberAt(i));
|
||||
} else if (ObjCForwardProtocolDeclaration *fProto = member->asObjCForwardProtocolDeclaration()) {
|
||||
addType(fProto->name());
|
||||
addProtocol(fProto->name());
|
||||
} else if (ObjCProtocol *proto = member->asObjCProtocol()) {
|
||||
addType(proto->name());
|
||||
addProtocol(proto->name());
|
||||
|
||||
for (unsigned i = 0; i < proto->memberCount(); ++i)
|
||||
buildMemberTypeMap(proto->memberAt(i));
|
||||
@@ -466,3 +481,53 @@ bool CheckUndefinedSymbols::visit(SizeofExpressionAST *ast)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckUndefinedSymbols::visit(ObjCClassDeclarationAST *ast)
|
||||
{
|
||||
if (NameAST *nameAST = ast->superclass) {
|
||||
bool resolvedSuperClassName = false;
|
||||
|
||||
if (Name *name = nameAST->name) {
|
||||
Identifier *id = name->identifier();
|
||||
const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size());
|
||||
if (isType(spell))
|
||||
resolvedSuperClassName = true;
|
||||
}
|
||||
|
||||
if (! resolvedSuperClassName) {
|
||||
translationUnit()->warning(nameAST->firstToken(),
|
||||
"expected class-name after ':' token");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckUndefinedSymbols::visit(ObjCProtocolRefsAST *ast)
|
||||
{
|
||||
for (IdentifierListAST *iter = ast->identifier_list; iter; iter = iter->next) {
|
||||
if (NameAST *nameAST = iter->name) {
|
||||
bool resolvedProtocolName = false;
|
||||
|
||||
if (Name *name = nameAST->name) {
|
||||
Identifier *id = name->identifier();
|
||||
const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size());
|
||||
if (isProtocol(spell))
|
||||
resolvedProtocolName = true;
|
||||
}
|
||||
|
||||
if (!resolvedProtocolName) {
|
||||
char after;
|
||||
|
||||
if (iter == ast->identifier_list)
|
||||
after = '<';
|
||||
else
|
||||
after = ',';
|
||||
|
||||
translationUnit()->warning(nameAST->firstToken(), "expected protocol name after '%c' token", after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -59,6 +59,8 @@ protected:
|
||||
void buildTypeMap(Class *klass);
|
||||
void buildMemberTypeMap(Symbol *member);
|
||||
void buildTypeMap(NamespaceBinding *binding, QSet<NamespaceBinding *> *processed);
|
||||
void addProtocol(Name *name);
|
||||
bool isProtocol(const QByteArray &name) const;
|
||||
|
||||
FunctionDeclaratorAST *currentFunctionDeclarator() const;
|
||||
CompoundStatementAST *compoundStatement() const;
|
||||
@@ -92,6 +94,9 @@ protected:
|
||||
virtual bool visit(CastExpressionAST *ast);
|
||||
virtual bool visit(SizeofExpressionAST *ast);
|
||||
|
||||
virtual bool visit(ObjCClassDeclarationAST *ast);
|
||||
virtual bool visit(ObjCProtocolRefsAST *ast);
|
||||
|
||||
private:
|
||||
Document::Ptr _doc;
|
||||
NamespaceBindingPtr _globalNamespaceBinding;
|
||||
@@ -100,6 +105,7 @@ private:
|
||||
QList<TemplateDeclarationAST *> _templateDeclarationStack;
|
||||
QList<CompoundStatementAST *> _compoundStatementStack;
|
||||
QSet<QByteArray> _types;
|
||||
QSet<QByteArray> _protocols;
|
||||
QSet<QByteArray> _namespaceNames;
|
||||
};
|
||||
|
||||
|
@@ -2359,6 +2359,8 @@ unsigned ObjCMethodPrototypeAST::lastToken() const
|
||||
{
|
||||
if (attributes)
|
||||
return attributes->lastToken();
|
||||
else if (dot_dot_dot_token)
|
||||
return dot_dot_dot_token + 1;
|
||||
else if (arguments)
|
||||
return arguments->lastToken();
|
||||
else if (type_name)
|
||||
|
@@ -2994,6 +2994,7 @@ public:
|
||||
ObjCTypeNameAST *type_name;
|
||||
ObjCSelectorAST *selector;
|
||||
ObjCMessageArgumentDeclarationListAST *arguments;
|
||||
unsigned dot_dot_dot_token;
|
||||
SpecifierAST *attributes;
|
||||
|
||||
public: // annotations
|
||||
|
@@ -137,6 +137,8 @@ class ForwardClassDeclaration;
|
||||
class Token;
|
||||
|
||||
// Objective-C symbols
|
||||
class ObjCBaseClass;
|
||||
class ObjCBaseProtocol;
|
||||
class ObjCClass;
|
||||
class ObjCForwardClassDeclaration;
|
||||
class ObjCProtocol;
|
||||
|
@@ -57,6 +57,7 @@
|
||||
#include "Control.h"
|
||||
#include "Literals.h"
|
||||
#include <cassert>
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
@@ -506,11 +507,25 @@ bool CheckDeclaration::visit(ObjCProtocolDeclarationAST *ast)
|
||||
ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, protocolName);
|
||||
protocol->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||
protocol->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||
ast->symbol = protocol;
|
||||
|
||||
if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
|
||||
for (IdentifierListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
|
||||
NameAST* name = iter->name;
|
||||
Name *protocolName = semantic()->check(name, _scope);
|
||||
ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
|
||||
protocol->addProtocol(baseProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Public);
|
||||
for (DeclarationListAST *it = ast->member_declarations; it; it = it->next) {
|
||||
semantic()->check(it->declaration, protocol->members());
|
||||
}
|
||||
(void) semantic()->switchObjCVisibility(previousObjCVisibility);
|
||||
|
||||
ast->symbol = protocol;
|
||||
_scope->enterSymbol(protocol);
|
||||
|
||||
// TODO EV: walk protocols and method prototypes
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -562,7 +577,21 @@ bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
|
||||
klass->setCategoryName(categoryName);
|
||||
}
|
||||
|
||||
// TODO: super-class, and protocols (EV)
|
||||
if (ast->superclass) {
|
||||
Name *superClassName = semantic()->check(ast->superclass, _scope);
|
||||
ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superClassName);
|
||||
klass->setBaseClass(superKlass);
|
||||
}
|
||||
|
||||
if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
|
||||
for (IdentifierListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
|
||||
NameAST* name = iter->name;
|
||||
Name *protocolName = semantic()->check(name, _scope);
|
||||
ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
|
||||
klass->addProtocol(baseProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
_scope->enterSymbol(klass);
|
||||
|
||||
int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Protected);
|
||||
@@ -627,4 +656,86 @@ bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
enum PropertyAttributes {
|
||||
None = 0,
|
||||
Assign = 1 << 0,
|
||||
Retain = 1 << 1,
|
||||
Copy = 1 << 2,
|
||||
ReadOnly = 1 << 3,
|
||||
ReadWrite = 1 << 4,
|
||||
Getter = 1 << 5,
|
||||
Setter = 1 << 6,
|
||||
NonAtomic = 1 << 7,
|
||||
|
||||
WritabilityMask = ReadOnly | ReadWrite,
|
||||
SetterSemanticsMask = Assign | Retain | Copy,
|
||||
};
|
||||
|
||||
bool CheckDeclaration::checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst,
|
||||
int &flags,
|
||||
int attr)
|
||||
{
|
||||
if (flags & attr) {
|
||||
translationUnit()->warning(attrAst->attribute_identifier_token,
|
||||
"duplicate property attribute \"%s\"",
|
||||
spell(attrAst->attribute_identifier_token));
|
||||
return false;
|
||||
} else {
|
||||
flags |= attr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
|
||||
{
|
||||
int propAttrs = None;
|
||||
|
||||
for (ObjCPropertyAttributeListAST *iter= ast->property_attributes; iter; iter = iter->next) {
|
||||
ObjCPropertyAttributeAST *attrAst = iter->attr;
|
||||
if (!attrAst)
|
||||
continue;
|
||||
|
||||
const char *attrName = spell(attrAst->attribute_identifier_token);
|
||||
if (!qstrcmp("getter", attrName)) {
|
||||
if (checkPropertyAttribute(attrAst, propAttrs, Getter)) {
|
||||
// TODO: find method declaration for getter
|
||||
}
|
||||
} else if (!qstrcmp("setter", attrName)) {
|
||||
if (checkPropertyAttribute(attrAst, propAttrs, Setter)) {
|
||||
// TODO: find method declaration for setter
|
||||
}
|
||||
} else if (!qstrcmp("readwrite", attrName)) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, ReadWrite);
|
||||
} else if (!qstrcmp("readonly", attrName)) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, ReadOnly);
|
||||
} else if (!qstrcmp("assign", attrName)) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, Assign);
|
||||
} else if (!qstrcmp("retain", attrName)) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, Retain);
|
||||
} else if (!qstrcmp("copy", attrName)) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, Copy);
|
||||
} else if (!qstrcmp("nonatomic", attrName)) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, NonAtomic);
|
||||
}
|
||||
}
|
||||
|
||||
if (propAttrs & ReadOnly && propAttrs & ReadWrite)
|
||||
// Should this be an error instead of only a warning?
|
||||
translationUnit()->warning(ast->property_token,
|
||||
"property can have at most one attribute \"readonly\" or \"readwrite\" specified");
|
||||
int setterSemAttrs = propAttrs & SetterSemanticsMask;
|
||||
if (setterSemAttrs
|
||||
&& setterSemAttrs != Assign
|
||||
&& setterSemAttrs != Retain
|
||||
&& setterSemAttrs != Copy) {
|
||||
// Should this be an error instead of only a warning?
|
||||
translationUnit()->warning(ast->property_token,
|
||||
"property can have at most one attribute \"assign\", \"retain\", or \"copy\" specified");
|
||||
}
|
||||
|
||||
// TODO: Check if the next line is correct (EV)
|
||||
semantic()->check(ast->simple_declaration, _scope);
|
||||
return false;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
@@ -97,7 +97,12 @@ protected:
|
||||
virtual bool visit(ObjCClassForwardDeclarationAST *ast);
|
||||
virtual bool visit(ObjCMethodDeclarationAST *ast);
|
||||
virtual bool visit(ObjCVisibilityDeclarationAST *ast);
|
||||
virtual bool visit(ObjCPropertyDeclarationAST *ast);
|
||||
|
||||
private:
|
||||
bool checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst,
|
||||
int &flags,
|
||||
int attr);
|
||||
private:
|
||||
DeclarationAST *_declaration;
|
||||
Scope *_scope;
|
||||
|
@@ -265,14 +265,15 @@ bool CheckDeclarator::visit(ObjCMethodPrototypeAST *ast)
|
||||
method->setReturnType(returnType);
|
||||
|
||||
if (ast->selector && ast->selector->asObjCSelectorWithArguments()) {
|
||||
// TODO: check the parameters (EV)
|
||||
// fun->setVariadic(...);
|
||||
// TODO: add arguments (EV)
|
||||
for (ObjCMessageArgumentDeclarationListAST *it = ast->arguments; it; it = it->next) {
|
||||
ObjCMessageArgumentDeclarationAST *argDecl = it->argument_declaration;
|
||||
|
||||
semantic()->check(argDecl, method->arguments());
|
||||
}
|
||||
|
||||
if (ast->dot_dot_dot_token)
|
||||
method->setVariadic(true);
|
||||
}
|
||||
|
||||
_fullySpecifiedType = FullySpecifiedType(method);
|
||||
|
@@ -416,8 +416,8 @@ bool CheckSpecifier::visit(AttributeSpecifierAST *ast)
|
||||
bool CheckSpecifier::visit(ObjCTypeNameAST * /*ast*/)
|
||||
{
|
||||
// TODO: implement this (EV)
|
||||
_fullySpecifiedType = FullySpecifiedType();
|
||||
return false;
|
||||
// _fullySpecifiedType = FullySpecifiedType();
|
||||
return true;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
@@ -128,6 +128,8 @@ public:
|
||||
delete_array_entries(enums);
|
||||
delete_array_entries(usingDeclarations);
|
||||
delete_array_entries(classForwardDeclarations);
|
||||
delete_array_entries(objcBaseClasses);
|
||||
delete_array_entries(objcBaseProtocols);
|
||||
delete_array_entries(objcClasses);
|
||||
delete_array_entries(objcProtocols);
|
||||
delete_array_entries(objcForwardClassDeclarations);
|
||||
@@ -348,6 +350,20 @@ public:
|
||||
return c;
|
||||
}
|
||||
|
||||
ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, Name *name)
|
||||
{
|
||||
ObjCBaseClass *c = new ObjCBaseClass(translationUnit, sourceLocation, name);
|
||||
objcBaseClasses.push_back(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, Name *name)
|
||||
{
|
||||
ObjCBaseProtocol *p = new ObjCBaseProtocol(translationUnit, sourceLocation, name);
|
||||
objcBaseProtocols.push_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
ObjCClass *newObjCClass(unsigned sourceLocation, Name *name)
|
||||
{
|
||||
ObjCClass *c = new ObjCClass(translationUnit, sourceLocation, name);
|
||||
@@ -561,6 +577,8 @@ public:
|
||||
std::vector<Enum *> enums;
|
||||
std::vector<UsingDeclaration *> usingDeclarations;
|
||||
std::vector<ForwardClassDeclaration *> classForwardDeclarations;
|
||||
std::vector<ObjCBaseClass *> objcBaseClasses;
|
||||
std::vector<ObjCBaseProtocol *> objcBaseProtocols;
|
||||
std::vector<ObjCClass *> objcClasses;
|
||||
std::vector<ObjCProtocol *> objcProtocols;
|
||||
std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
|
||||
@@ -740,6 +758,12 @@ ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLoca
|
||||
Name *name)
|
||||
{ return d->newForwardClassDeclaration(sourceLocation, name); }
|
||||
|
||||
ObjCBaseClass *Control::newObjCBaseClass(unsigned sourceLocation, Name *name)
|
||||
{ return d->newObjCBaseClass(sourceLocation, name); }
|
||||
|
||||
ObjCBaseProtocol *Control::newObjCBaseProtocol(unsigned sourceLocation, Name *name)
|
||||
{ return d->newObjCBaseProtocol(sourceLocation, name); }
|
||||
|
||||
ObjCClass *Control::newObjCClass(unsigned sourceLocation, Name *name)
|
||||
{ return d->newObjCClass(sourceLocation, name); }
|
||||
|
||||
|
@@ -166,6 +166,9 @@ public:
|
||||
/// Creates a new ForwardClassDeclaration symbol.
|
||||
ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name = 0);
|
||||
|
||||
ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, Name *name);
|
||||
ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, Name *name);
|
||||
|
||||
/// Creates a new Objective-C class symbol.
|
||||
ObjCClass *newObjCClass(unsigned sourceLocation, Name *name = 0);
|
||||
|
||||
|
@@ -51,6 +51,19 @@ static inline int classify3(const char *s) {
|
||||
return Token_identifier;
|
||||
}
|
||||
|
||||
static inline int classify4(const char *s) {
|
||||
if (s[0] == 'c') {
|
||||
if (s[1] == 'o') {
|
||||
if (s[2] == 'p') {
|
||||
if (s[3] == 'y') {
|
||||
return Token_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Token_identifier;
|
||||
}
|
||||
|
||||
static inline int classify5(const char *s) {
|
||||
if (s[0] == 'b') {
|
||||
if (s[1] == 'y') {
|
||||
@@ -78,7 +91,20 @@ static inline int classify5(const char *s) {
|
||||
}
|
||||
|
||||
static inline int classify6(const char *s) {
|
||||
if (s[0] == 'b') {
|
||||
if (s[0] == 'a') {
|
||||
if (s[1] == 's') {
|
||||
if (s[2] == 's') {
|
||||
if (s[3] == 'i') {
|
||||
if (s[4] == 'g') {
|
||||
if (s[5] == 'n') {
|
||||
return Token_assign;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s[0] == 'b') {
|
||||
if (s[1] == 'y') {
|
||||
if (s[2] == 'c') {
|
||||
if (s[3] == 'o') {
|
||||
@@ -91,6 +117,32 @@ static inline int classify6(const char *s) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s[0] == 'g') {
|
||||
if (s[1] == 'e') {
|
||||
if (s[2] == 't') {
|
||||
if (s[3] == 't') {
|
||||
if (s[4] == 'e') {
|
||||
if (s[5] == 'r') {
|
||||
return Token_getter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s[0] == 's') {
|
||||
if (s[1] == 'e') {
|
||||
if (s[2] == 't') {
|
||||
if (s[3] == 't') {
|
||||
if (s[4] == 'e') {
|
||||
if (s[5] == 'r') {
|
||||
return Token_setter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s[0] == 'o') {
|
||||
if (s[1] == 'n') {
|
||||
if (s[2] == 'e') {
|
||||
@@ -104,6 +156,81 @@ static inline int classify6(const char *s) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s[0] == 'r') {
|
||||
if (s[1] == 'e') {
|
||||
if (s[2] == 't') {
|
||||
if (s[3] == 'a') {
|
||||
if (s[4] == 'i') {
|
||||
if (s[5] == 'n') {
|
||||
return Token_retain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Token_identifier;
|
||||
}
|
||||
|
||||
static inline int classify8(const char *s) {
|
||||
if (s[0] == 'r') {
|
||||
if (s[1] == 'e') {
|
||||
if (s[2] == 'a') {
|
||||
if (s[3] == 'd') {
|
||||
if (s[4] == 'o') {
|
||||
if (s[5] == 'n') {
|
||||
if (s[6] == 'l') {
|
||||
if (s[7] == 'y') {
|
||||
return Token_readonly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Token_identifier;
|
||||
}
|
||||
|
||||
static inline int classify9(const char *s) {
|
||||
if (s[0] == 'n') {
|
||||
if (s[1] == 'o') {
|
||||
if (s[2] == 'n') {
|
||||
if (s[3] == 'a') {
|
||||
if (s[4] == 't') {
|
||||
if (s[5] == 'o') {
|
||||
if (s[6] == 'm') {
|
||||
if (s[7] == 'i') {
|
||||
if (s[8] == 'c') {
|
||||
return Token_nonatomic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (s[0] == 'r') {
|
||||
if (s[1] == 'e') {
|
||||
if (s[2] == 'a') {
|
||||
if (s[3] == 'd') {
|
||||
if (s[4] == 'w') {
|
||||
if (s[5] == 'r') {
|
||||
if (s[6] == 'i') {
|
||||
if (s[7] == 't') {
|
||||
if (s[8] == 'e') {
|
||||
return Token_readwrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Token_identifier;
|
||||
}
|
||||
|
||||
@@ -111,8 +238,11 @@ int classifyObjectiveCTypeQualifiers(const char *s, int n) {
|
||||
switch (n) {
|
||||
case 2: return classify2(s);
|
||||
case 3: return classify3(s);
|
||||
case 4: return classify4(s);
|
||||
case 5: return classify5(s);
|
||||
case 6: return classify6(s);
|
||||
case 8: return classify8(s);
|
||||
case 9: return classify9(s);
|
||||
default: return Token_identifier;
|
||||
} // switch
|
||||
}
|
||||
|
@@ -37,10 +37,18 @@ CPLUSPLUS_BEGIN_NAMESPACE
|
||||
enum {
|
||||
Token_in,
|
||||
Token_out,
|
||||
Token_copy,
|
||||
Token_byref,
|
||||
Token_inout,
|
||||
Token_assign,
|
||||
Token_bycopy,
|
||||
Token_getter,
|
||||
Token_retain,
|
||||
Token_setter,
|
||||
Token_oneway,
|
||||
Token_readonly,
|
||||
Token_nonatomic,
|
||||
Token_readwrite,
|
||||
Token_identifier
|
||||
};
|
||||
|
||||
|
@@ -4544,7 +4544,13 @@ bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *a
|
||||
last->comma_token = consumeToken();
|
||||
last->next = new (_pool) ObjCPropertyAttributeListAST;
|
||||
last = last->next;
|
||||
parseObjCPropertyAttribute(last->attr);
|
||||
if (!parseObjCPropertyAttribute(last->attr)) {
|
||||
_translationUnit->error(_tokenIndex, "expected token `%s' got `%s'",
|
||||
Token::name(T_IDENTIFIER), tok().spell());
|
||||
while (LA() != T_RPAREN)
|
||||
consumeToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4597,15 +4603,15 @@ bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node)
|
||||
lastArg->argument_declaration = declaration;
|
||||
}
|
||||
|
||||
// TODO EV: get this in the ast
|
||||
while (LA() == T_COMMA) {
|
||||
consumeToken();
|
||||
|
||||
if (LA() == T_DOT_DOT_DOT) {
|
||||
consumeToken();
|
||||
ast->dot_dot_dot_token = consumeToken();
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Is this still valid, and if so, should it be stored in the AST? (EV)
|
||||
DeclarationAST *parameter_declaration = 0;
|
||||
parseParameterDeclaration(parameter_declaration);
|
||||
}
|
||||
@@ -4639,28 +4645,43 @@ bool Parser::parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node)
|
||||
return false;
|
||||
|
||||
node = new (_pool) ObjCPropertyAttributeAST;
|
||||
match(T_IDENTIFIER, &(node->attribute_identifier_token));
|
||||
if (LA() == T_EQUAL) {
|
||||
node->equals_token = consumeToken();
|
||||
|
||||
unsigned identifier_token = 0;
|
||||
match(T_IDENTIFIER, &identifier_token);
|
||||
Identifier *id = tok().identifier;
|
||||
const int k = classifyObjectiveCTypeQualifiers(id->chars(), id->size());
|
||||
switch (k) {
|
||||
case Token_copy:
|
||||
case Token_assign:
|
||||
case Token_retain:
|
||||
case Token_readonly:
|
||||
case Token_readwrite:
|
||||
case Token_nonatomic:
|
||||
node->attribute_identifier_token = consumeToken();
|
||||
return true;
|
||||
|
||||
if (LA() == T_COLON) {
|
||||
case Token_getter: {
|
||||
node->attribute_identifier_token = consumeToken();
|
||||
match(T_EQUAL, &(node->equals_token));
|
||||
ObjCSelectorWithoutArgumentsAST *selector = new (_pool) ObjCSelectorWithoutArgumentsAST;
|
||||
match(T_IDENTIFIER, &(selector->name_token));
|
||||
node->method_selector = selector;
|
||||
return true;
|
||||
}
|
||||
|
||||
case Token_setter: {
|
||||
node->attribute_identifier_token = consumeToken();
|
||||
match(T_EQUAL, &(node->equals_token));
|
||||
ObjCSelectorWithArgumentsAST *selector = new (_pool) ObjCSelectorWithArgumentsAST;
|
||||
selector->selector_arguments = new (_pool) ObjCSelectorArgumentListAST;
|
||||
selector->selector_arguments->argument = new (_pool) ObjCSelectorArgumentAST;
|
||||
selector->selector_arguments->argument->name_token = identifier_token;
|
||||
selector->selector_arguments->argument->colon_token = consumeToken();
|
||||
match(T_IDENTIFIER, &(selector->selector_arguments->argument->name_token));
|
||||
match(T_COLON, &(selector->selector_arguments->argument->colon_token));
|
||||
node->method_selector = selector;
|
||||
} else {
|
||||
ObjCSelectorWithoutArgumentsAST *selector = new (_pool) ObjCSelectorWithoutArgumentsAST;
|
||||
selector->name_token = identifier_token;
|
||||
node->method_selector = selector;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN
|
||||
|
@@ -210,6 +210,9 @@ public:
|
||||
/// Returns true if this Symbol is a ForwardClassDeclaration.
|
||||
bool isForwardClassDeclaration() const;
|
||||
|
||||
bool isObjCBaseClass() const;
|
||||
bool isObjCBaseProtocol() const;
|
||||
|
||||
/// Returns true if this Symbol is an Objective-C Class declaration.
|
||||
bool isObjCClass() const;
|
||||
|
||||
@@ -237,6 +240,8 @@ public:
|
||||
virtual const Argument *asArgument() const { return 0; }
|
||||
virtual const BaseClass *asBaseClass() const { return 0; }
|
||||
virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; }
|
||||
virtual const ObjCBaseClass *asObjCBaseClass() const { return 0; }
|
||||
virtual const ObjCBaseProtocol *asObjCBaseProtocol() const { return 0; }
|
||||
virtual const ObjCClass *asObjCClass() const { return 0; }
|
||||
virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const { return 0; }
|
||||
virtual const ObjCProtocol *asObjCProtocol() const { return 0; }
|
||||
@@ -255,6 +260,8 @@ public:
|
||||
virtual Argument *asArgument() { return 0; }
|
||||
virtual BaseClass *asBaseClass() { return 0; }
|
||||
virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; }
|
||||
virtual ObjCBaseClass *asObjCBaseClass() { return 0; }
|
||||
virtual ObjCBaseProtocol *asObjCBaseProtocol() { return 0; }
|
||||
virtual ObjCClass *asObjCClass() { return 0; }
|
||||
virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() { return 0; }
|
||||
virtual ObjCProtocol *asObjCProtocol() { return 0; }
|
||||
|
@@ -81,6 +81,8 @@ public:
|
||||
virtual bool visit(ForwardClassDeclaration *) { return true; }
|
||||
|
||||
// Objective-C
|
||||
virtual bool visit(ObjCBaseClass *) { return true; }
|
||||
virtual bool visit(ObjCBaseProtocol *) { return true; }
|
||||
virtual bool visit(ObjCClass *) { return true; }
|
||||
virtual bool visit(ObjCForwardClassDeclaration *) { return true; }
|
||||
virtual bool visit(ObjCProtocol *) { return true; }
|
||||
|
@@ -561,6 +561,32 @@ void Class::visitSymbol0(SymbolVisitor *visitor)
|
||||
}
|
||||
}
|
||||
|
||||
ObjCBaseClass::ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
|
||||
: Symbol(translationUnit, sourceLocation, name)
|
||||
{ }
|
||||
|
||||
ObjCBaseClass::~ObjCBaseClass()
|
||||
{ }
|
||||
|
||||
FullySpecifiedType ObjCBaseClass::type() const
|
||||
{ return FullySpecifiedType(); }
|
||||
|
||||
void ObjCBaseClass::visitSymbol0(SymbolVisitor *visitor)
|
||||
{ visitor->visit(this); }
|
||||
|
||||
ObjCBaseProtocol::ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
|
||||
: Symbol(translationUnit, sourceLocation, name)
|
||||
{ }
|
||||
|
||||
ObjCBaseProtocol::~ObjCBaseProtocol()
|
||||
{ }
|
||||
|
||||
FullySpecifiedType ObjCBaseProtocol::type() const
|
||||
{ return FullySpecifiedType(); }
|
||||
|
||||
void ObjCBaseProtocol::visitSymbol0(SymbolVisitor *visitor)
|
||||
{ visitor->visit(this); }
|
||||
|
||||
ObjCClass::ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name):
|
||||
ScopedSymbol(translationUnit, sourceLocation, name),
|
||||
_categoryName(0),
|
||||
|
@@ -476,6 +476,48 @@ private:
|
||||
Array<BaseClass *> _baseClasses;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ObjCBaseClass: public Symbol
|
||||
{
|
||||
public:
|
||||
ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
|
||||
virtual ~ObjCBaseClass();
|
||||
|
||||
// Symbol's interface
|
||||
virtual FullySpecifiedType type() const;
|
||||
|
||||
virtual const ObjCBaseClass *asObjCBaseClass() const
|
||||
{ return this; }
|
||||
|
||||
virtual ObjCBaseClass *asObjCBaseClass()
|
||||
{ return this; }
|
||||
|
||||
protected:
|
||||
virtual void visitSymbol0(SymbolVisitor *visitor);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ObjCBaseProtocol: public Symbol
|
||||
{
|
||||
public:
|
||||
ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
|
||||
virtual ~ObjCBaseProtocol();
|
||||
|
||||
// Symbol's interface
|
||||
virtual FullySpecifiedType type() const;
|
||||
|
||||
virtual const ObjCBaseProtocol *asObjCBaseProtocol() const
|
||||
{ return this; }
|
||||
|
||||
virtual ObjCBaseProtocol *asObjCBaseProtocol()
|
||||
{ return this; }
|
||||
|
||||
protected:
|
||||
virtual void visitSymbol0(SymbolVisitor *visitor);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ObjCForwardProtocolDeclaration: public Symbol, public Type
|
||||
{
|
||||
public:
|
||||
@@ -511,6 +553,15 @@ public:
|
||||
ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
|
||||
virtual ~ObjCProtocol();
|
||||
|
||||
unsigned protocolCount() const
|
||||
{ return _protocols.count(); }
|
||||
|
||||
ObjCBaseProtocol *protocolAt(unsigned index) const
|
||||
{ return _protocols.at(index); }
|
||||
|
||||
void addProtocol(ObjCBaseProtocol *protocol)
|
||||
{ _protocols.push_back(protocol); }
|
||||
|
||||
// Symbol's interface
|
||||
virtual FullySpecifiedType type() const;
|
||||
|
||||
@@ -534,7 +585,7 @@ protected:
|
||||
virtual void accept0(TypeVisitor *visitor);
|
||||
|
||||
private:
|
||||
Array<ObjCProtocol *> _protocols;
|
||||
Array<ObjCBaseProtocol *> _protocols;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ObjCForwardClassDeclaration: public Symbol, public Type
|
||||
@@ -579,18 +630,18 @@ public:
|
||||
Name *categoryName() const { return _categoryName; }
|
||||
void setCategoryName(Name *categoryName) { _categoryName = categoryName; }
|
||||
|
||||
ObjCClass *baseClass() const
|
||||
ObjCBaseClass *baseClass() const
|
||||
{ return _baseClass; }
|
||||
void setBaseClass(ObjCClass *baseClass)
|
||||
void setBaseClass(ObjCBaseClass *baseClass)
|
||||
{ _baseClass = baseClass; }
|
||||
|
||||
unsigned protocolCount() const
|
||||
{ return _protocols.count(); }
|
||||
|
||||
ObjCProtocol *protocolAt(unsigned index) const
|
||||
ObjCBaseProtocol *protocolAt(unsigned index) const
|
||||
{ return _protocols.at(index); }
|
||||
|
||||
void addProtocol(ObjCProtocol *protocol)
|
||||
void addProtocol(ObjCBaseProtocol *protocol)
|
||||
{ _protocols.push_back(protocol); }
|
||||
|
||||
// Symbol's interface
|
||||
@@ -618,8 +669,8 @@ protected:
|
||||
private:
|
||||
bool _isInterface;
|
||||
Name *_categoryName;
|
||||
ObjCClass * _baseClass;
|
||||
Array<ObjCProtocol *> _protocols;
|
||||
ObjCBaseClass * _baseClass;
|
||||
Array<ObjCBaseProtocol *> _protocols;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ObjCMethod: public ScopedSymbol, public Type
|
||||
|
Reference in New Issue
Block a user