-
Notifications
You must be signed in to change notification settings - Fork 629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Make isIncludeFile() return TRUE for files with an unknown extension #3696
Conversation
The idea sounds reasonable to me, defaulting to non-local in doubt is probably safer.
Shouldn't this include whether the declaration is |
I simplified this one a bit just for the sake of the problem of this PR where this isn't relevant. For function definitions (i.e. functions with bodies) the parser really checks whether they are static or not. For function declarations (i.e. function prototypes without bodies) it doesn't check for the Back to this patch, I was also thinking it would maybe be more appropriate to introduce a new function
Note that if
then |
@techee indeed that makes even more sense, and can thus be used as best fits the caller, depending on the actual use for the information. And indeed here the question is rather whether it's definitely a source file rather than not definitely a header. |
@masatake do you have an opinion here? |
BTW, a couple of things you can figure out by grepping:
So I think whether or not there should be both So I would think that the best solution is to forget entirely about "is this a header", and replace the whole concept with "is this definitely not a header?" (and so, the probably more reasonable user option "is this a source file? (rather than a header)"), possibly including replacing the related option altogether. |
(Catching up slowly) |
I'm sorry for not getting back to you sooner. As a code reader, I think the However, as a ctags developer, I want to delete it from ctags. The e.g.
It is hard to know whether Let's think about short-term solutions. I wonder if we extend
Instead of listing the file extension for headers, make ctags accept the file extensions for none headers like:
Geany can pass the extensions for non-headers to ctags before running ctags. p.s.
|
The code I illustrated for my idea:
|
But is there any such field based on which clients could decide whether it's a local or a non-local declaration (e.g. whether a function is The
Sounds good and I think that makes sense for ctags if you want to preserve some compatibility with existing tools. I'm just wondering if
shouldn't be the default when
I'm wondering if we can do it somehow (I didn't investigate it though). Remember we are just calling some internal ctags functions like in the |
See the "p.s." in my last comment.
ctags also records
Though About
Extending the interface for Geany is the next step. I believe it is not hard. |
Cool, I wasn't aware of that. In this case I'm actually wondering whether it's worth introducing any changes in ctags - I think we'll be able to flag those file scope tags by ourselves. Especially if the defaults for
I'm aware of that but you can never be sure whether some include file is used or not because you can have code like
and |
So the refined issue here is the design of the new API for using the "properties:" field of C and C++ parsers. Alright? |
Maybe there's already everything present but if you could give me a hint, it would be great. If I understand correctly, the "properties" field is stored into Lines 1009 to 1021 in 5ba7dfc
The only problem is how to get the Line 95 in 5ba7dfc
Even though the index will probably be |
mini-geany helps us! $ git diff | cat
diff --git a/main/entry.c b/main/entry.c
index 9e2601213..cfb3f5a2a 100644
--- a/main/entry.c
+++ b/main/entry.c
@@ -1020,7 +1020,7 @@ extern const tagField* getParserFieldForIndex (const tagEntryInfo * tag, int ind
}
}
-extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype)
+extern const char* getParserFieldValueForType (const tagEntryInfo *const tag, fieldType ftype)
{
for (int i = 0; i < tag->usedParserFields; i++)
{
diff --git a/main/entry.h b/main/entry.h
index 21d9f60ae..7b27aeae6 100644
--- a/main/entry.h
+++ b/main/entry.h
@@ -298,7 +298,7 @@ extern bool isTagExtra (const tagEntryInfo *const tag);
*/
extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char* value);
extern void attachParserFieldToCorkEntry (int index, fieldType ftype, const char* value);
-extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype);
+extern const char* getParserFieldValueForType (const tagEntryInfo *const tag, fieldType ftype);
extern int makePlaceholder (const char *const name);
extern void markTagAsPlaceholder (tagEntryInfo *e, bool placeholder);
diff --git a/main/mini-geany.c b/main/mini-geany.c
index 0f0571995..24390d1b9 100644
--- a/main/mini-geany.c
+++ b/main/mini-geany.c
@@ -27,6 +27,11 @@
#include <string.h>
#include <errno.h>
+langType C_lang = LANG_IGNORE;
+langType CXX_lang = LANG_IGNORE;
+fieldType c_props_ft = FIELD_UNKNOWN; /* Ideally, this should be passed via clientData of writeEntry(, ...) */
+fieldType cxx_props_ft = FIELD_UNKNOWN; /* Ideally, this should be passed via clientData of writeEntry(, ...) */
+
static int writeEntry (tagWriter *writer, MIO * mio, const tagEntryInfo *const tag, void *clientData);
static void rescanFailed (tagWriter *writer, unsigned long validTagNum, void *clientData);
@@ -209,6 +214,7 @@ typedef struct {
unsigned long lineNumber;
int lang;
bool isAnon;
+ bool isStatic;
} Tag;
@@ -234,6 +240,11 @@ static Tag *createTag(const tagEntryInfo *info)
tag->lineNumber = info->lineNumber;
tag->lang = info->langType;
tag->isAnon = isTagExtraBitMarked(info, XTAG_ANONYMOUS);
+
+ const char *props = (info->langType == C_lang)? getParserFieldValueForType (info, c_props_ft):
+ (info->langType == CXX_lang)? getParserFieldValueForType (info, cxx_props_ft): NULL;
+ tag->isStatic = (props && !!strstr(props, "static"));
+
return tag;
}
@@ -306,11 +317,12 @@ static void processCollectedTags(ptrArray *tagArray)
for (i = 0; i < num; i++)
{
Tag *tag = ptrArrayItem(tagArray, i);
- printf("%s\tline: %lu\tkind: %s\t lang: %s\n",
+ printf("%s\tline: %lu\tkind: %s\t lang: %s%s\n",
tag->name,
tag->lineNumber,
ctagsGetKindName(tag->kindLetter, tag->lang),
- ctagsGetLangName(tag->lang));
+ ctagsGetLangName(tag->lang),
+ tag->isStatic? " [static]": "");
}
/* prepare for the next parsing by clearing the tag array */
@@ -323,6 +335,15 @@ extern int main (int argc, char **argv)
/* called once when Geany starts */
ctagsInit();
+ {
+ C_lang = getNamedLanguage("C", 0);
+ c_props_ft = getFieldTypeForNameAndLanguage ("properties", C_lang);
+ enableField (c_props_ft, true);
+ CXX_lang = getNamedLanguage("C++", 0);
+ cxx_props_ft = getFieldTypeForNameAndLanguage ("properties", CXX_lang);
+ enableField (cxx_props_ft, true);
+ }
+
/* create empty tag array *
* this is where we store the collected tags
* NOTE: Geany doesn't use the ptrArray type - it is used just for the purpose of this demo */
|
The changes for entry.[ch] are already merged in #3699. |
@masatake Thanks! After some thinking, though, I think for us it will be easiest to still rely on The code you provided could still be interesting for us in the future if we decide we'd like to get some info from some parser-specific fields. |
@techee I see I already wrote code for the |
This PR is inspired by the problem reported here in Geany:
geany/geany#3454
Basically the problem is that if ctags parses a file with an unknown file extension, the
isIncludeFile()
function returnsfalse
which makes the code at various places in C/C++ parser likeset
tag->isFileScope = true
. I think that when we don't know for sure whether a file is a header or source, it would be safer to treat it as a header and not to generate thefileScope
extras flag for it (see more in geany/geany#3457 (comment)).I'm posting this as a draft here only for further discussion. The patch makes unit tests fail (I didn't want to spend time on it unless I know this PR is something that is wanted in ctags), misses a unit test and also the documentation of the
-h
command-line option should be changed. Since all files would be treated as headers by default, the only use for-h
would be to override source files like*.c
to be treated as headers.