[geany/geany] 808612: PHP: parse namespaces

Colomban Wendling git-noreply at xxxxx
Wed Jul 3 17:42:13 UTC 2013


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Mon, 15 Apr 2013 16:55:52 UTC
Commit:      8086129c9c26c49700798bdb27da85b75cc1ca49
             https://github.com/geany/geany/commit/8086129c9c26c49700798bdb27da85b75cc1ca49

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


More information about the Commits mailing list