2020-06-21

Little surprises #5: qmake edition

The last edition of "Little surprises" reminded my of an incident from a while ago.

This one involves the input file format fo Qt's qmake tool.

Like a lot of other tools, the input language uses # to indicate a comment extending to the end of the line, and \ as the last charqacter on a line to indicate line continuation (the current logical line is extended to include the next file line). It also uses lists of white-space separated tokens as in:

SUBDIRS=external-library module1 module2 tests

If a list gets to have more than a few entries, it can be made much more readable by using line continuation:

SUBDIRS = external-library \
          module1 \
          module2 \
          tests   # Should anything go here?

A practice further encourage if you use Qt creator because the IDE builds lists of files and directories in this way.

What about the last line?

Should you put a line continuation marker on the last line of such a list?1

Pros:
  • consistency (which may appeal to any obsessive tendency that you might have)
  • reduces the number of ways to make a mistake if you reoder the list
Cons
  • you don't need to
  • you need to worry about what is on the next line, introducing a new way to make mistakes

As I can be a little obsessive about consistency in code and insist on a whitespace line after a list like that anyway I choose to put the trailing continuation in there. The thing that I discovered is that in qmake the "need to worry about what goes on the next line" bit includes comments. That is, if I write

SUBDIRS = external-library \
          module1 \
          module2 \
          tests \
# Explanation of what I want to do next
ANOTHER_KEYWORD

The system will consider ANOTHER_KEYWORD as an item on the list.

I'm not aware that this is documented anywhere.

What?

From my point of view this the violates the principle of least surprise. If I append the comment to the line containing test, then I have a end-of-line comment and that should be the end of it. That said, if I think about actually parsing a file like this I can see two implementation strategies that would lead to this behavior as a side-effect,2 and though they are not the ones I would have chosen I don't think they are dumb either.

Arguably this lends weight to the "don't do that" side of the argument about continuing the last line, but I have chosen instead keep the consistency and insist that such a list must be trailed by a empty line.


1 This kind of question doesn't come up in my mind alone. Note that C++ enum offers explicit support for ending the list with a comma.

2 (A) Multiple passes with comment elimination coming before line continuation and full line comments removed entirely. (B) Line-at-a-time parsing and full line comments are handled by silently loading the next line.

No comments:

Post a Comment