universal-ctags / citre

A superior code reading & auto-completion tool with pluggable backends.
GNU General Public License v3.0
326 stars 26 forks source link

Accurate inspection on C struct members #83

Closed AmaiKinono closed 4 months ago

AmaiKinono commented 3 years ago

Several Citre users talked about this idea to me.

If we are at:

foo.bar|

(| is the cursor), we could:

  1. Find the definitons of foo (we could assume it's a variable, function parameter, or member (maybe more?)).
  2. Find the typeref fields of these definitions. They should be typeref:struct:structName (if there are more than 1 definitons, multiple structName is possible.
  3. Sort the definitions of bar so those with struct:structName scope field are on the top.

I need to learn more on how a C file is tagged:

Also, some users want struct member completion in this situation:

foo.|

We could do 1 and 2 the same as above, then:

I'd like to take the latter approach. The infrastructure of Citre needs some mild modify to support it, though.

If we could solve this, the design can be used for other static type languages, too. If we could also find the way of dealing with inheritance, I'd say Citre will have the potential of becoming the best tool for static type languages with class/subtype or even other fancy type systems.

masatake commented 3 years ago

If everything can be done in ctags/readtags, it is nice. If we don't seek the above ideal, there are more choices. which-function-mode tells us the current scope. You can call readtags to find foo with (eq? $scope-name (the-scope-information-getting-from-which-mode)).

masatake commented 3 years ago

Using https://github.com/universal-ctags/python-ctags3 is just another choice.

AmaiKinono commented 3 years ago
  1. which-function-mode actually uses imenu, AFAIK. imenu doesn't know where does a scope end, so it can't tell you the current scope accurately.

  2. I didn't see connection between the question I described and the current scope.

    What I want is:

    • find the symbol before .
    • find the tags of the symbol (it should be a struct instance)
    • find the type of those tags (some kind of a struct)
    • now we know the symbol after . should be a member of that struct. We can sort those results above others.
masatake commented 3 years ago
  • find the tags of the symbol (it should be a struct instance) (B)

(B) can be done in readtags. However, readtags may provide multiple candidates.

struct port {
   uint16_t num;
   enum protocol proto;
};

extern struct port p;
void print_point(struct point p)
{
    printf("%d %d\n", p.|
}

How can we know the type of p? readtags may report:

p   foo.c   /^extern struct port p;$/;" x   typeref:struct:port
p   foo.c   /^void print_point(struct point p)$/;"  z   function:print_point    typeref:struct:point    file:

If we know the cursor is in print_point, citre can choose the latter one.

a tag entry of C language can have line: and end: fields. So we can implement (B) only with readtags. However, it will need a linear search that we don't want to do.

BTW we cannot forget typedef.

struct point;
typedef struct point Point;
Point p;

In that case, citre must run readtags repeatedly.

AmaiKinono commented 3 years ago

readtags may provide multiple candidates... If we know the cursor is in print_point, citre can choose the latter one.

I see.

a tag entry of C language can have line: and end: fields. So we can implement (B) only with readtags. However, it will need a linear search that we don't want to do.

Also, this won't work if the file has been edited, so the line length of the function is no longer (- end-field line-field).

What we could do is do some parsing in Citre to find the current function.

Using which-function-mode is not a choice because it uses imenu, and when citre-mode is on, imenu does a linear search on the tags file.

Also, when we couldn't do better, we can just use all definitons of p. The point is not to do a complete semantic analysis, but trying to be accurate when guessing things.

BTW we cannot forget typedef. In that case, citre must run readtags repeatedly.

Thanks, I didn't thought about typedef. I'm prepared to running readtags multiple times, though.

masatake commented 3 years ago

Using which-function-mode is not a choice because it uses imenu, and when citre-mode is on, imenu does a linear search on the tags file.

In such a case, you can turn off citre-mode temporarily.

AmaiKinono commented 4 months ago

As discussed in the developer manual, we've decided to not take the approach to filter accurately as this may throw away actually useful tags. So I'll close this.