예제 #1
0
static void show_entry(tagEntry *entry)
{
	const gchar *kind;
	const gchar *signature;
	const gchar *scope;
	const gchar *file;
	const gchar *name;
	gchar *scope_str;
	gchar *kind_str;

	file = entry->file;
	if (!file)
		file = "";

	name = entry->name;
	if (!name)
		name = "";

	signature = tagsField(entry, "signature");
	if (!signature)
		signature = "";

	scope = tagsField(entry, "class");
	if (!scope)
		scope = tagsField(entry, "struct");
	if (!scope)
		scope = tagsField(entry, "union");
	if (!scope)
		scope = tagsField(entry, "enum");

	if (scope)
		scope_str = g_strconcat(scope, "::", NULL);
	else
		scope_str = g_strdup("");

	kind = entry->kind;
	if (kind)
	{
		kind_str = g_strconcat(kind, ":  ", NULL);
		SETPTR(kind_str, g_strdup_printf("%-14s", kind_str));
	}
	else
		kind_str = g_strdup("");

	msgwin_msg_add(COLOR_BLACK, -1, NULL, "%s:%lu:\n    %s%s%s%s", file,
		entry->address.lineNumber, kind_str, scope_str, name, signature);

	g_free(scope_str);
	g_free(kind_str);
}
예제 #2
0
bool Parse::getScopeAndLocals(Scope * sc, const QString &expr, const QString &ident)
{
	// initialize scope if nothing better is found
	sc->scope = "";
	sc->localdef = "";

	/* create a tags file for `expr' with function names only.
	 * The function with the highest line number is our valid scope
	 * --sort=no, because tags generation probably faster, and
	 * so I just have to look for the last entry to find 'my' tag
	 */

	QString command =
	    ctagsCmdPath +
	    " --language-force=c++ --sort=no --fields=fKmnsz --c++-kinds=fn -o \"" +
	    smallTagsFilePath + "\" \"" + parsedFilePath + '\"';

	// I don't process any user input, so system() should be safe enough
	QProcess ctags;
	ctags.execute(command);
	QFile::remove (parsedFilePath);
	if (ctags.exitStatus() == QProcess::CrashExit)
		return false;

	/* find the last entry, this is our current scope */
	tagFileInfo info;
	tagFile *tfile = tagsOpen(smallTagsFilePath.toAscii(), &info);
	tagEntry entry;
	const char *scope = NULL;
	if (tfile && info.status.opened)
	{
		if (tagsFirst(tfile, &entry) == TagSuccess)
		{
			do
				scope = tagsField(&entry, "class");
			while (tagsNext(tfile, &entry) == TagSuccess);
		}
		tagsClose(tfile);
	}

	/* must be before the 'type = extract_type_qualifier()' code, which modifies scope */
	if (scope)
		sc->scope = scope;

	/* get local definition (if any) */
	if (ident!="")
	{
		QString type = extractTypeQualifier(expr, ident);
		if (type.length())
		{
			sc->localdef = type;
		}
		else
			sc->localdef = "";
	}

	QFile::remove (smallTagsFilePath);
	
	return true;
}
예제 #3
0
QString Parse::getTypeOfToken(const QString &ident, const QString &className,
                              Scope * scope, bool token_is_function)
{
	/* if we have a variable and already found a local definition, just return it after duplicating */
	if (!token_is_function && scope->localdef.length())
		return scope->localdef;

	/* if the identifier is this-> return the current class */
	if (ident == "this")
		return scope->scope;

	Tree *tree = NULL;
	if (className.length())
	{
		tree = Tree::buildInheritanceTree(className);
		if (!tree)
			return NULL;
	}

	tagFileInfo info;
	tagEntry entry;
	tagFile *tfile = tagsOpen(tagsFilePath.toAscii(), &info);
	if (tfile && info.status.opened)
	{
		if (tagsFind(tfile, &entry, ident.toAscii(), TAG_OBSERVECASE | TAG_FULLMATCH) ==
		        TagSuccess)
		{
			do
			{
				if (tree && !tree->isMemberOfScope(&entry, scope))
					continue;

				const char *kind = tagsField(&entry, "kind");
				if (token_is_function)	/* only list if tag is a function */
				{
					if (!kind
					        || (strcmp(kind, "function") && strcmp(kind, "prototype")))
						continue;
				}
				else		/* or a variable */
				{
					//brc: add externvar for extern variables like cout
					if (!kind
					        || (strcmp(kind, "variable") && strcmp(kind, "externvar")
					            //brc: namespace workarround: add namespace
					            && strcmp(kind, "namespace") && strcmp(kind, "member")))
						continue;
				}

				/* need to duplicate the pattern, don't ask me why */
				QString type = extractTypeQualifier(entry.address.pattern, ident);
				if(tree)
					tree->freeTree();
				tagsClose(tfile);
				return type;
			}
			while (tagsFindNext(tfile, &entry) == TagSuccess);
		}
		tagsClose(tfile);
	}
	return NULL;
}
예제 #4
0
Tag Parse::prettifyTag(const tagEntry * entry)
{
	const char *signature = tagsField(entry, "signature");
	const char *kind = tagsField(entry, "kind");
	const char *access = tagsField(entry, "access");

	Tag tag;
	tag.isFunction = signature;
	tag.name = entry->name;

	char *p = (char *) entry->address.pattern;

	/* for a macro the pattern is already parsed */
	if (!strcmp(kind, "macro"))
	{
		/* NOTE: exuberant-ctags 5.5.4 does not provide a valid pattern for found macros
		 * work around it, by getting the line myself */
		char pat_macro[512];
		unsigned long line = entry->address.lineNumber;
		if (line == 0)		/* sometimes ctags can't find the correct line */
			return tag;

		FILE *fileMacro = fopen(entry->file, "r");
		if (fileMacro)
		{
			while ((p = fgets(pat_macro, 512, fileMacro)) != NULL)
			{
				line--;
				if (line <= 0)
				{
					/* remove leading spaces */
					p++;	/* skip over # - it is added later again */
					while (*p == ' ' || *p == '\t')
						p++;

					tag.longName = '#' + p;
					/* remove new line at the end */
					tag.longName.remove(tag.longName.length() - 1, 1);
					break;
				}
			}
			tag.longName += " [macro]";
			fclose(fileMacro);
			return tag;
		}
	}
	/* special handling for enumerator */
	if (!strcmp(kind, "enumerator"))
	{
		/* skip whitespace from variable/function patterns */
		size_t skip = strspn(p, "/^ \t");
		p += skip;
		/* remove trailing $/ characters */
		char *pos = NULL;
		if ((pos = strstr(p, "$/")) != NULL)
			*pos = '\0';
		/* replace \/\/ and \/ * *\/ to correctly show comments */
		while ((pos = strstr(p, "\\/\\/")) != NULL)
			memcpy(pos, "  //", 4);
		while ((pos = strstr(p, "\\/*")) != NULL)
			memcpy(pos, " /*", 3);
		while ((pos = strstr(p, "*\\/")) != NULL)
			memcpy(pos, " */", 3);

		tag.longName += QString(p) + " [enumerator]";
		return tag;
	}

	size_t skip = strspn(p, "/^ \t");
	p += skip;
	/* remove trailing $/ characters */
	char *pos = NULL;
	if ((pos = strstr(p, "$/")) != NULL)
		*pos = '\0';

	tag.longName += p;

	/* if it is a function, add signature as well */
	if (signature)
		tag.parameters += signature;

	if (access && (!strcmp(access, "private") || !strcmp(access, "protected")))
		tag.longName += '[' + access + ']';

	return tag;
}