better-cpp-syntax icon indicating copy to clipboard operation
better-cpp-syntax copied to clipboard

#else and #endif have incorrect colorization when in the middle of a function declaration parameter list

Open sean-mcmanus opened this issue 4 years ago • 3 comments

Checklist

  • [ yes ] This problem exists even with the setting "C_Cpp.enhancedColorization": "Disabled"
  • [ yes ] This bug exists for C
  • [ no ] This bug exists for C++
  • [ ?] This bug exists for Objective-C
  • [ ? ] This bug exists for Objective-C++

The code with a problem is:

#if FOO
int func(int,
#else
double func(int, 
#endif
int);

It looks like:

image

Dark+ Theme

It should look like:

Not red, like #if.

This could be a duplicate, but it was hard for me to tell.

sean-mcmanus avatar Jul 02 '20 23:07 sean-mcmanus

Duplicate of #31, but this one is a bit clearer about the problem.

@jeff-hykin I don't believe the following potential solution has been discussed before.

  1. #ifdef and #endif are just patterns inserted into every context

  2. #else starts a new pattern range that ends with lookahead for #endif or #else

  3. is needed because if all conditional preprocessor directives were just match-rules then the context for the code that follows will be wrong.

Image if the match-rules for those directives had an effect on the rest of the grammar as to make them disappear. The new source would be

int func(int,
double func(int,
int);

any code that follows that would be parsed as if it is in a function definition. The ability for preprocessor ranges to jump contexts means at least one of the paths has to be discarded.

Though there will still be issues similar to #299 with this solution

enum items {
item1,
item2,
#if foo
item3,
#else
item3_v2, // this is not colored like an enum member
#endif
item4
};

I should be able to resume contributing sometime next week.

matter123 avatar Jul 03 '20 00:07 matter123

I think its not a duplicate cause this case isn't broken on C++ only C.

@matter123 Yeah I think that is a more clear version of strategy 2 from #31 There are some edge cases though like #if #elseif #end to make sure to cover. Once that general method is implemented I think that will be the best that can ever be done with the textmate parser.

jeff-hykin avatar Jul 10 '20 18:07 jeff-hykin

To clarify:

  • #if, #ifdef and #ifndef do not start a range
  • #else and #elif do start a range, which end on a look ahead for #else, #elif or #endif
  • #endif does not end a range

Even if the previous point is fixed, (by duplicating the range for each context), The context of the ranges will actually be influenced by the contents of the #if block. So it is likely, by itself, not a solution to this issue. The correct solution is incredibly expensive, and that is to create a unique pattern for every possible combination of contexts so that the #else to #endif can use the parent context. A good enough effort is to introduce the root scope back into the possibilities.

matter123 avatar Jul 10 '20 19:07 matter123