Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Mon, 15 Apr 2013 16:55:52 UTC Commit: 8086129c9c26c49700798bdb27da85b75cc1ca49 https://github.com/geany/geany/commit/8086129c9c26c49700798bdb27da85b75cc1ca...
Log Message: ----------- PHP: parse namespaces
PHP namespaces don't work anything like a block, so the implementation is specific and not combined with scope management. Namespaces cannot be nested, and they may apply either to the rest of the file (until the next namespace declaration, if any) or to a specific block.
Namespaces applying to the rest of the file:
namespace Foo; /* code in namespace Foo */ namespace Bar\Baz; /* code in namespace Bar\Baz */
Namespaces applying to blocks:
namespace Foo { /* code in namespace Foo */ } namespace Bar\Baz { /* code in namespace Bar\Baz */ } namespace { /* code in root namespace */ }
Modified Paths: -------------- tagmanager/ctags/php.c
Modified: tagmanager/ctags/php.c 101 files changed, 96 insertions(+), 5 deletions(-) =================================================================== @@ -20,6 +20,9 @@ #include "entry.h"
+#define SCOPE_SEPARATOR "." /* "::" */ + + typedef enum { KEYWORD_NONE = -1, KEYWORD_abstract, @@ -101,6 +104,7 @@ K_FUNCTION, K_INTERFACE, K_LOCAL_VARIABLE, + K_NAMESPACE, K_VARIABLE, COUNT_KIND } phpKind; @@ -111,6 +115,7 @@ { TRUE, 'f', "function", "functions" }, { TRUE, 'i', "interface", "interfaces" }, { FALSE, 'l', "local", "local variables" }, + { TRUE, 'n', "namespace", "namespaces" }, { TRUE, 'v', "variable", "variables" } };
@@ -225,6 +230,9 @@ struct { implType impl; } CurrentStatement;
+/* Current namespace */ +vString *CurrentNamesapce; +
static void buildPhpKeywordHash (void) { @@ -266,6 +274,20 @@ static const char *implToString (const implType impl) static void initPhpEntry (tagEntryInfo *const e, const tokenInfo *const token, const phpKind kind, const accessType access) { + static vString *fullScope = NULL; + int parentKind = -1; + + if (fullScope == NULL) + fullScope = vStringNew (); + else + vStringClear (fullScope); + + if (vStringLength (CurrentNamesapce) > 0) + { + vStringCopy (fullScope, CurrentNamesapce); + parentKind = K_NAMESPACE; + } + initTagEntry (e, vStringValue (token->string));
e->lineNumber = token->lineNumber; @@ -275,12 +297,20 @@ static void initPhpEntry (tagEntryInfo *const e, const tokenInfo *const token,
if (access != ACCESS_UNDEFINED) e->extensionFields.access = accessToString (access); - if (vStringLength(token->scope) > 0) + if (vStringLength (token->scope) > 0) + { + parentKind = token->parentKind; + if (vStringLength (fullScope) > 0) + vStringCatS (fullScope, SCOPE_SEPARATOR); + vStringCat (fullScope, token->scope); + } + if (vStringLength (fullScope) > 0) { - Assert (token->parentKind >= 0); + Assert (parentKind >= 0);
- e->extensionFields.scope[0] = PhpKinds[token->parentKind].name; - e->extensionFields.scope[1] = vStringValue (token->scope); + vStringTerminate (fullScope); + e->extensionFields.scope[0] = PhpKinds[parentKind].name; + e->extensionFields.scope[1] = vStringValue (fullScope); } }
@@ -296,6 +326,23 @@ static void makeSimplePhpTag (const tokenInfo *const token, const phpKind kind, } }
+static void makeNamespacePhpTag (const tokenInfo *const token, const vString *const name) +{ + if (PhpKinds[K_NAMESPACE].enabled) + { + tagEntryInfo e; + + initTagEntry (&e, vStringValue (name)); + + e.lineNumber = token->lineNumber; + e.filePosition = token->filePosition; + e.kindName = PhpKinds[K_NAMESPACE].name; + e.kind = (char) PhpKinds[K_NAMESPACE].letter; + + makeTagEntry (&e); + } +} + static void makeClassOrIfaceTag (const phpKind kind, const tokenInfo *const token, vString *const inheritance, const implType impl) { @@ -438,7 +485,7 @@ static void printToken (const tokenInfo *const token) static void addToScope (tokenInfo *const token, const vString *const extra) { if (vStringLength (token->scope) > 0) - vStringCatS (token->scope, "." /* "::" */); + vStringCatS (token->scope, SCOPE_SEPARATOR); vStringCatS (token->scope, vStringValue (extra)); vStringTerminate(token->scope); } @@ -1071,6 +1118,46 @@ static boolean parseVariable (tokenInfo *const token) return readNext; }
+/* parses namespace declarations + * namespace Foo {} + * namespace Foo\Bar {} + * namespace Foo; + * namespace Foo\Bar; + * namespace; + * napespace {} */ +static boolean parseNamespace (tokenInfo *const token) +{ + tokenInfo *nsToken = newToken (); + + vStringClear (CurrentNamesapce); + copyToken (nsToken, token, FALSE); + + do + { + readToken (token); + if (token->type == TOKEN_IDENTIFIER) + { + if (vStringLength (CurrentNamesapce) > 0) + vStringPut (CurrentNamesapce, '\'); + vStringCat (CurrentNamesapce, token->string); + } + } + while (token->type != TOKEN_EOF && + token->type != TOKEN_SEMICOLON && + token->type != TOKEN_OPEN_CURLY); + + vStringTerminate (CurrentNamesapce); + if (vStringLength (CurrentNamesapce) > 0) + makeNamespacePhpTag (nsToken, CurrentNamesapce); + + if (token->type == TOKEN_OPEN_CURLY) + enterScope (token, NULL, -1); + + deleteToken (nsToken); + + return TRUE; +} + static void enterScope (tokenInfo *const parentToken, const vString *const extraScope, const int parentKind) @@ -1107,6 +1194,8 @@ static void enterScope (tokenInfo *const parentToken, case KEYWORD_const: readNext = parseConstant (token); break; case KEYWORD_define: readNext = parseDefine (token); break;
+ case KEYWORD_namespace: readNext = parseNamespace (token); break; + case KEYWORD_private: CurrentStatement.access = ACCESS_PRIVATE; break; case KEYWORD_protected: CurrentStatement.access = ACCESS_PROTECTED; break; case KEYWORD_public: CurrentStatement.access = ACCESS_PUBLIC; break; @@ -1141,6 +1230,7 @@ static void findPhpTags (void) InPhp = FALSE; CurrentStatement.access = ACCESS_UNDEFINED; CurrentStatement.impl = IMPL_UNDEFINED; + CurrentNamesapce = vStringNew ();
do { @@ -1148,6 +1238,7 @@ static void findPhpTags (void) } while (token->type != TOKEN_EOF); /* keep going even with unmatched braces */
+ vStringDelete (CurrentNamesapce); deleteToken (token); }
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).