-
Notifications
You must be signed in to change notification settings - Fork 622
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
Cxx: extract parameters in a prototype #3063
Cxx: extract parameters in a prototype #3063
Conversation
Close universal-ctags#3060. input.h: template <class T> int f (T t); The scope kind for T was function. It should be prototype.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
C++ rejects using "this" as a nmae of a parameter. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Codecov Report
@@ Coverage Diff @@
## master #3063 +/- ##
==========================================
+ Coverage 87.33% 87.37% +0.04%
==========================================
Files 199 199
Lines 47611 47732 +121
==========================================
+ Hits 41579 41704 +125
+ Misses 6032 6028 -4
Continue to review full report at Codecov.
|
fe4ab03
to
93badee
Compare
Currently the function parameters are enabled via +z which is "function parameters inside function definitions". |
I think using the same switch 'z' for both function parameters and prototype parameters is better. The following shows how the pull request works: $ cat input.c
cat input.c
void p(int x);
void f(int y)
{
}
$ ./ctags -o - input.c
./ctags -o - input.c
f input.c /^void f(int y)$/;" f language:C typeref:typename:void
$ ./ctags -o - --kinds-C=+p input.c
./ctags -o - --kinds-C=+p input.c
f input.c /^void f(int y)$/;" f language:C typeref:typename:void
p input.c /^void p(int x);$/;" p language:C typeref:typename:void file:
$ ./ctags -o - --kinds-C=+z input.c
./ctags -o - --kinds-C=+z input.c
f input.c /^void f(int y)$/;" f language:C typeref:typename:void
y input.c /^void f(int y)$/;" z language:C function:f typeref:typename:int file:
$ ./ctags -o - --kinds-C=+zp input.c
./ctags -o - --kinds-C=+zp input.c
f input.c /^void f(int y)$/;" f language:C typeref:typename:void
p input.c /^void p(int x);$/;" p language:C typeref:typename:void file:
x input.c /^void p(int x);$/;" z language:C prototype:p typeref:typename:int file:
y input.c /^void f(int y)$/;" z language:C function:f typeref:typename:int file:
$ ./ctags -o - --kinds-C=+zp-f input.c
./ctags -o - --kinds-C=+zp-f input.c
p input.c /^void p(int x);$/;" p language:C typeref:typename:void file:
x input.c /^void p(int x);$/;" z language:C prototype:p typeref:typename:int file:
y input.c /^void f(int y)$/;" z language:C function:f typeref:typename:int file: In this pull request, ctags doesn't emit tags for parameters of a prototype if the prototype kind is disabled <1>. In the most of all parsers I wrote, I implemented the behavior <2>: tagging children even if the kind for their parent object is disabled. However, in this pull request I chose <1> because emitting tags for parameters of prototype when disabling prototype kind looks too noisy. @pragmaware, how I should do? |
Close universal-ctags#3045. If types of parameters are declared in a prototype, this change generates anonymous names for them and makes tags.
93badee
to
a22956a
Compare
Well, they obviously refer to the same "physical" parameters, so in this sense they are the same. However, the usage by the ctags clients may be very different. Take the very common operation of "completion": most editors that use ctags do that. The parameters of the function are essentially local variables: one wants to complete them in the scope of the function and thus they are very useful. The parameters of the prototype have no such role: one never wants to complete them or even to look them up by name. The only use of prototype parameters is to help analyzing the signature of the function "from outside", for example when filling the arguments of the call. But that's a rather advanced feature, few editors really have it and now that I look at it ctags doesn't even have enough information to implement it that way (index of the parameter is missing). My editor, for instance, has the first feature (completion) but has no use for the parameters of the prototype: it would discard them. That's why I'd like to keep function parameters on but prototype parameters off. But in the end, it's not a big deal: they are easy to filter out, now that they are marked with the "prototype" scope.
From an editor-using-ctags perspective they are kind-of similar. Inside a function definition the template parameters are placeholders for types. One completes and resolves them like types in the function body. The prototype ones, again, are used as map/translation but never as completion. Editors fully handling template parameters are even more exotic beasts...
I agree... though for the prototype template parameters nobody would notice if we added another kind :)
Makes sense. I can't think of a good reason one would want to see the prototype parameters but not the prototypes... |
Thank you for the suggestive comment.
Yes. I have been thinking about adding "nth:" as a COMMON field. input.c:
expected.tags:
(signature fields are omitted in this example.) I'm also thinking about arity: field. I'm not sure how useful it is. About template parameter(tparam), whether a tparam is for template prototype or template function can be known from its scope field. See f281087 included in this pull request or #3062. |
I found nth: field is not enough if the target language, like C++, supports overloading. input.cc:
u-ctags --sort=no --fields=+oS --kinds-C++=+zp -o - input.cc | grep ^x
I wonder how about introducing
|
Yes, this is a general problem with overloads, not only related to the nth field. In my editor I solve it by looking at line numbers. However, ctags internally has the hierarchy information in this case so it could be output in some way. For example, we could assign a synthetic unique identifier to the parent symbol (function definition) and reference it in the child symbol (parameter)... this would be unambiguous. |
Now that I think of it, it's not only a problem with overloads. It's potentially with any symbol. For example, when taking into consideration a large C/C++ code base, possibly including libraries, it's not uncommon to have multiple classes with the same name in the global namespace. Or maybe the same static helper function repeated in many cpp files... It's just enough to make sure the compiler can see only one of these symbols at a time. I believe this can happen also in most other languages. So a tree-building ctags client has always to solve the child-parent matching problem in some way. File+line-number matching is one way but it's not 100% reliable. Having unique ids for symbols would be a nice addition. |
Do you think cork-indexes are appropriate as the ids? To improve ctags in the view of this topic, I thought what we needed. A. tags.d. Managing whole the source tree in a tags file is hard. I'm thinking about per-source file tags files. tags.d is a name of directory where the tags files are stored. This allows incremental updating. B. filesystem langauge. ctags is a file oriented program. It doesn't consider relation between two input files. C. multi-pass parsing. An experimental implementation is proposed in #2741. #2471 reads a tags file as hint. I must read whole the tags file. If the tags file is larger, loading takes more time. Instead of dealing a tags file, tags files under tags.d may allow on-demand loading. I'm not sure these are the way to go. |
@pragmaware, can I merge this pull request? |
Anything unique in the context of a tags file will do. If the cork indexes are unique and don't change then they are OK.
I must say that a tags file by itself has limited application. When it's properly sorted it can be reasonably used to lookup a single symbol at a time without consideration of scope. However this is only the most basic form of "developer assistance". Most IDEs and code editors do far more than that and use derived structures that are more complex (and efficient) than a tag file. In fact, in code3 case the tags file is never really written to disk. ctags is launched on subtrees of code (whole source tree, an include directory, a single file as it is being edited and so on) and its standard output is processed directly into memory. The memory structure is called "symbol store" and is composed of different pieces:
If you want to take a look, the symbol store is here, while the symbol tree parts are here. This whole structure allows the editor to quickly do complex and accurate completions. Say that the user is editing the following file with the cursor placed at position
If the user now presses tab, the editor will:
Quite complicated process. In more involved cases may take a noticeable time with optimized in-memory structures. Totally unfeasible with only a tag file. I don't think ctags should try to do this process internally. The reasons are:
What is mean is simply: the tags file is good as it is. It's just a plain symbol storage format. I think ctags should:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go for it!
A cork index is unique in a input file. However, it can be duplicated. So unique id for each input file is needed in addition to the cork index. |
Just use a global integer incremented at each new symbol? |
Close #3045.
Parameters in functions were tagged.
This change extends it.
With this change, parameters in prototypes are tagged.
It is usual that a parameter in a prototype has no name. In such a case, this change generates an anonymous name.