Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

CDT/Obsolete/C editor enhancements/Include management

This is a problem page. Please treat it as a discussion page and feel free to insert your comments anywhere. My open questions are in bold--Tomasz Wesołowski 14:22, 30 April 2010 (UTC)

Problem

Description

The management of #include directives is probably one of the most repetitive tasks in C++ programming.

There's already an "Add include" feature, but it has its drawbacks: needs manual invocation by the programmer and is inaccurate in numerous situations. Clearly there's a lot of space for improvement.

Ranking

4/5 Sergey Prigogin 07:16, 18 May 2010 (UTC)

4/5 Tobias Hahn 09:32, 18 May 2010 (UTC)

Inspiration

JDT features wonderful include handling. If the Java include path is set correctly, then the programmer probably never has to add an import manually and is thus not distracted from actual coding.

The addition of new import can be done in two ways: when selecting a class from Context Assist which is not yet imported, or by invoking Organize Includes. JDT also warns about and allows to remove unused imports.

Solution proposal

A possible solution is to make CDT work like JDT. The problem gets a bit more complex in C++, though.

Invocation

A JDT-like solution would be to integrate adding includes with Context Assist.

Implementing a JDT-like solution would require little change to Context Assist behaviour. Context Assist, when invoked from a context with a part of name entered, would need to display a set of indexed symbols; ideally:

  • sorted in a clever way - how exactly?,
    • [Markus Schorn] Be aware that (different to Java) reordering inclusions can change the compilation unit.
  • with the not-yet-included elements annotated in-place with the defining file).

A selection of not-yet-included option would invoke the include directive generation.

Possible tools includes:

  • Checkers/Quick fixes
    • Find unused includes
    • Find indirect includes used (i.e. we use a.h but we don't include it but we include b.h which includes a.h)
    • Find all files that needs to be included
  • Refactoring
    • Sort includes
    • Remove all unused/Flattern (include directly used)
  • Editor
    • Folding

Generation

The generation of an #include directive also is not a trivial task, as it is in Java.

There are 2 decisions to be made:

1) How to include. This part is quite nicely handled by the Add include function, as it uses <header.h> if it can be reached by the project's include paths or "path/to/header.h" from current file if it can be reached by the file system. I believe it's the expected behaviour.

Depending on include path, the same file can be included differently. Consider, for example, the following two files: /project_root/some_dir/file.h and /project_root/some_dir/file.cpp If /project_root is included in include path, then file.h can be included in file.cpp either as "file.h" or as "some_dir/file.h" (Sergey Prigogin).

2) What to include. In case of classes, we might need either a simple declaration or a definition - the feature should decide which one is required. This problem can be illustrated by the scenario of "Add Include" feature stubbornly including iosfwd instead of expected iostream. (side note: This fact is confusing, as iosfwd only contains class forward declarations.)

As the guidelines say that headers should be light: Would it be acceptable by this feature to introduce a forward declaration of a class instead of including the full header to reduce compilation times, if we can show that a full declaration isn't needed in a given context?

Some header files are not intended for direct inclusion. For example, std::set is defined in bits/stl_set.h, which contains a comment: "This is an internal header file, included by other library headers. You should not attempt to use it directly.". It is a well known fact that in order to use std::set somebody has to include <set>, not <bits/stl_set.h>. Unfortunately, CDT currently doesn't know about that rule (Sergey Prigogin).

3) Where to include. Order of include sometimes important. Conditional compilations, comments, includes mixed with code complicates things a lot (Elaskavaia.cdt.gmail.com 18:52, 17 May 2010 (UTC))

Unused includes marking

Such feature could be implemented as a Codan checker.

This task may be more tricky to implement than in Java. To decide if a header is used, we'd also need to check symbols in a compilation unit against all headers included by it, recursively. Browsing a big hierarchy of headers against occurrences of a given symbol might be time-consuming on bigger projects.

Java has "flat" imports, so this problem doesn't exist there.

Do you believe that such feature is neccessary?

  • [Markus Schorn]: In general you will not be able to determine whether a header file needs to be included. Here are a few different examples for that:
    • Including a file that contains inline function definitions: The compiler does not need the definitions, the linker will complain.
    • Including a file that contains #undef statements: You will not find references for the undefined macro, however removing the statement may change the way your code is compiled.
      • It can be detected too - i.e. if it is not used by any header below it and compilation unit - it won't affect it (Elaskavaia.cdt.gmail.com 18:49, 17 May 2010 (UTC))
    • Similar for #pragma statements that affect the way code is compiled.
    • Headers that are necessary dependent on compiler switches.
      • You mean header that are included (or not) using conditional compilation? (Elaskavaia.cdt.gmail.com 18:49, 17 May 2010 (UTC))
  • Elaskavaia.cdt.gmail.com 18:49, 17 May 2010 (UTC)
    • Yes it is not error prone however I think checker like that would be very useful. User should judge if he wants to remove header or not manually. I have done such checker before it can easily take a month on its own (plus other include checkers).
  • [Kirstin Weber]: I think support for includes is very helpful. It it one of the great features for Java and I really miss it when I write C++ code again. In Java unnecessary imports are marked immediately. If this is too time-consuming or hard/impossible to find out for C++ immediately it would be helpful if there would be a "clean up" function, perhaps after compiling. You compile the code and afterwards you invoke such a feature and all unnecessary imports are removed. You can use such a feature when you have finished your implementation in order to clean up your code at the end.

Folding

A little handy detail related to this problem would be to provide a possibility to fold a block of include directives.


References

Bug 45203 requests some functionality to organize includes.

Bug 291977 suggests the method of include management described here,

Bug 182897 and Bug 113063 describe problems with current "Add Include" feature.

Back to the top