C# Parser Fails (Root ERROR Node) with Nested Preprocessor Directives Conditionally Defining Method Parameters · Issue #377 · tree-sitter/tree-sitter-c-sharp · GitHub
Skip to content

C# Parser Fails (Root ERROR Node) with Nested Preprocessor Directives Conditionally Defining Method Parameters #377

Description

@pavlo-shchelkun

The tree-sitter-csharp parser fails and produces a root ERROR node when encountering nested C# preprocessor directives (#if ... #else ... #endif) that conditionally alter a method's signature, specifically its parameter list.

Environment:

  • py-tree-sitter version: 0.24.0
  • tree-sitter-language-pack version: 0.7.3
  • tree-sitter-csharp grammar version: 0.23.1
  • tree-sitter-embedded-template grammar version: 0.23.2
  • Operating System: macOS Sonoma 14.5

Minimal Reproducible Example:

// test_conditional_signature.cs
namespace TestNs
{
    public class TestClass
    {
#if OUTER_CONDITION // Outer preprocessor block
    #if INNER_CONDITION // Inner preprocessor block
        static void MyMethod() // Signature 1: no parameters
    #else
        static void MyMethod(int param) // Signature 2: with parameters
    #endif
        {
            // Common method body
        }
#endif
    }
}

Observed Behavior:
When parsing the above code, tree.root_node.type is ERROR and tree.root_node.has_error is True.

Expected Behavior:
The parser should correctly parse this valid C# construct, recognizing the method declaration with its conditionally defined parameter list. The root node should be compilation_unit and has_error should be False. Tree-sitter should parse the structure including both potential branches of the inner #if/#else.

Note:
If the method signature is not fragmented by inner preprocessor directives, it parses correctly. For example, if only one signature is used within the outer conditional block:

// This parses correctly:
namespace TestNs
{
    public class TestClass
    {
#if OUTER_CONDITION
        static void MyMethod(int param) 
        {
            // Common method body
        }
#endif
    }
}

This suggests an issue with the grammar's ability to handle preprocessor directives appearing within the syntactic structure of a method's parameter list definition. While preprocessor directives are often in extras, their interaction with the rules for parameter_list or method_declaration seems problematic in this nested scenario.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions