Skip to content

feat(lang): add C and C++ language support#2746

Open
davehenton wants to merge 3 commits intomainfrom
feat/c-cpp-maintainability-support
Open

feat(lang): add C and C++ language support#2746
davehenton wants to merge 3 commits intomainfrom
feat/c-cpp-maintainability-support

Conversation

@davehenton
Copy link
Copy Markdown
Member

Summary

  • Add tree-sitter-based C and C++ language implementations for maintainability analysis (complexity, duplication, nested control flow, etc.)
  • Wire up tree-sitter dependencies, language registration in ALL_LANGS, file type/extension mappings, and protobuf enum mappings
  • Add integration test fixtures and test registration for both C and C++

Test plan

  • Unit tests pass for both C and C++ language modules (11 tests)
  • Integration tests pass for both c_tests and cpp_tests
  • cargo check passes cleanly
  • CI passes

🤖 Generated with Claude Code

davehenton and others added 2 commits April 8, 2026 19:27
Wire up tree-sitter-based C and C++ language implementations including
tree-sitter dependencies, language registration, file type/extension
mappings, protobuf enum mappings, and integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add test fixtures and test registration for C language support,
mirroring the existing C++ test structure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@qltysh
Copy link
Copy Markdown
Contributor

qltysh bot commented Apr 9, 2026

Qlty

Coverage Impact - ubuntu-latest

⬆️ Merging this pull request will increase total coverage on main by 0.13%.

Modified Files with Diff Coverage (3)

RatingFile% DiffUncovered Line #s
Coverage rating: D Coverage rating: D
qlty-types/src/lib.rs100.0%
New file Coverage rating: A
qlty-analysis/src/lang/c.rs99.0%205, 227
New file Coverage rating: A
qlty-analysis/src/lang/cpp.rs99.1%229, 243
Total99.0%
🤖 Increase coverage with AI coding...

In the `feat/c-cpp-maintainability-support` branch, add test coverage for this new code:

- `qlty-analysis/src/lang/c.rs` -- Lines 205 and 227
- `qlty-analysis/src/lang/cpp.rs` -- Lines 229 and 243

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@qltysh
Copy link
Copy Markdown
Contributor

qltysh bot commented Apr 9, 2026

Qlty

Coverage Impact - macos-15

⬆️ Merging this pull request will increase total coverage on main by 0.13%.

Modified Files with Diff Coverage (3)

RatingFile% DiffUncovered Line #s
Coverage rating: D Coverage rating: D
qlty-types/src/lib.rs100.0%
New file Coverage rating: A
qlty-analysis/src/lang/c.rs99.0%205, 227
New file Coverage rating: A
qlty-analysis/src/lang/cpp.rs99.1%229, 243
Total99.0%
🤖 Increase coverage with AI coding...

In the `feat/c-cpp-maintainability-support` branch, add test coverage for this new code:

- `qlty-analysis/src/lang/c.rs` -- Lines 205 and 227
- `qlty-analysis/src/lang/cpp.rs` -- Lines 229 and 243

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@davehenton davehenton marked this pull request as ready for review April 9, 2026 20:57
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, reopen this pull request to trigger a review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class C and C++ support to qlty’s tree-sitter-based maintainability analysis pipeline, wiring language registration/config globs and providing CLI integration fixtures to exercise the end-to-end flow.

Changes:

  • Introduce new c and cpp language implementations in qlty-analysis and register them in ALL_LANGS.
  • Add workspace dependencies (tree-sitter-c, tree-sitter-cpp) and protobuf/enum + default config mappings for c/cpp.
  • Add CLI integration fixtures and test registration for C and C++.

Reviewed changes

Copilot reviewed 28 out of 29 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
qlty-types/src/lib.rs Maps "c"/"cpp" string names to protobuf Language enums.
qlty-config/default.toml Adds file_types and language glob mappings for C/C++.
qlty-cli/tests/lang/cpp/basic.toml Adds a basic C++ CLI integration test case.
qlty-cli/tests/lang/cpp/basic.in/Returns.cpp C++ fixture for return-statements behavior.
qlty-cli/tests/lang/cpp/basic.in/parameters.cpp C++ fixture for parameter counting behavior.
qlty-cli/tests/lang/cpp/basic.in/NestedControl.cpp C++ fixture for nested control-flow behavior.
qlty-cli/tests/lang/cpp/basic.in/Identical.cpp C++ fixture for identical-code behavior.
qlty-cli/tests/lang/cpp/basic.in/FunctionComplexity.cpp C++ fixture for function complexity behavior.
qlty-cli/tests/lang/cpp/basic.in/FileComplexity.cpp C++ fixture for file complexity behavior.
qlty-cli/tests/lang/cpp/basic.in/BooleanLogic.cpp C++ fixture for boolean-logic behavior.
qlty-cli/tests/lang/cpp/basic.in/.qlty/qlty.toml Minimal per-fixture qlty config for C++ tests.
qlty-cli/tests/lang/cpp/basic.in/.gitignore Ignores generated .qlty/ outputs in C++ fixtures.
qlty-cli/tests/lang/c/basic.toml Adds a basic C CLI integration test case.
qlty-cli/tests/lang/c/basic.in/returns.c C fixture for return-statements behavior.
qlty-cli/tests/lang/c/basic.in/parameters.c C fixture for parameter counting behavior.
qlty-cli/tests/lang/c/basic.in/nested_control.c C fixture for nested control-flow behavior.
qlty-cli/tests/lang/c/basic.in/identical.c C fixture for identical-code behavior.
qlty-cli/tests/lang/c/basic.in/function_complexity.c C fixture for function complexity behavior.
qlty-cli/tests/lang/c/basic.in/file_complexity.c C fixture for file complexity behavior.
qlty-cli/tests/lang/c/basic.in/boolean_logic.c C fixture for boolean-logic behavior.
qlty-cli/tests/lang/c/basic.in/.qlty/qlty.toml Minimal per-fixture qlty config for C tests.
qlty-cli/tests/lang/c/basic.in/.gitignore Ignores generated .qlty/ outputs in C fixtures.
qlty-cli/tests/lang.rs Registers c_tests and cpp_tests in the CLI test suite.
qlty-analysis/src/lang/cpp.rs Implements C++ AST node kinds + queries and identifier extraction via tree-sitter-cpp.
qlty-analysis/src/lang/c.rs Implements C AST node kinds + queries and identifier extraction via tree-sitter-c.
qlty-analysis/src/lang.rs Adds mod c; mod cpp; and registers them in ALL_LANGS.
qlty-analysis/Cargo.toml Adds tree-sitter-c and tree-sitter-cpp workspace dependencies.
Cargo.toml Adds workspace package versions for tree-sitter-c and tree-sitter-cpp.
Cargo.lock Locks new tree-sitter C/C++ crates and their transitive deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +14 to +16
declarator: (function_declarator
declarator: (identifier) @name
parameters: (parameter_list) @parameters)) @definition.function
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FUNCTION_DECLARATION_QUERY only matches function_definition nodes whose declarator is a function_declarator with a direct (identifier) child. This will miss many valid C function definitions where the declarator is wrapped (e.g., pointer/array declarators) or otherwise not a bare identifier, which will cause functions/parameters/returns/complexity smells to be silently undercounted. Consider broadening the query to match nested declarators and rely on function_name_node() to extract the final identifier, while still capturing the parameters node for downstream checks.

Suggested change
declarator: (function_declarator
declarator: (identifier) @name
parameters: (parameter_list) @parameters)) @definition.function
declarator: [
(function_declarator
parameters: (parameter_list) @parameters)
(pointer_declarator
declarator: (function_declarator
parameters: (parameter_list) @parameters))
(parenthesized_declarator
(function_declarator
parameters: (parameter_list) @parameters))
(parenthesized_declarator
(pointer_declarator
declarator: (function_declarator
parameters: (parameter_list) @parameters)))
]) @definition.function

Copilot uses AI. Check for mistakes.
const FIELD_QUERY: &str = r#"
(struct_specifier
body: (field_declaration_list
(field_declaration) @name)) @field
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIELD_QUERY captures @field on the surrounding struct_specifier and @name on the entire field_declaration. The metrics code expects the field capture to be the actual field node (so filtering/parent checks behave correctly) and the name capture to be the field’s identifier; capturing the whole declaration will also fail to split multi-declarator lines (e.g., int a, b;). Adjust the query to capture each field declarator/identifier as @name and tag the actual field declaration node as @field.

Suggested change
(field_declaration) @name)) @field
(field_declaration
declarator: (field_identifier) @name) @field))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (pointer_declarator
declarator: (field_identifier) @name)) @field))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (array_declarator
declarator: (field_identifier) @name)) @field))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (function_declarator
declarator: (field_identifier) @name)) @field))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (parenthesized_declarator
(field_identifier) @name)) @field))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (parenthesized_declarator
(pointer_declarator
declarator: (field_identifier) @name)) @field)))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (parenthesized_declarator
(array_declarator
declarator: (field_identifier) @name)) @field)))
(struct_specifier
body: (field_declaration_list
(field_declaration
declarator: (parenthesized_declarator
(function_declarator
declarator: (field_identifier) @name)) @field)))

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +21
(function_definition
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters)) @definition.function
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FUNCTION_DECLARATION_QUERY requires the function_definition’s declarator field to be a function_declarator. In tree-sitter C/C++ grammars, function declarators are often wrapped (e.g., pointer_declarator, parenthesized_declarator), and this query will then miss legitimate function definitions, breaking parameter/return/complexity checks. Consider expanding the query to match nested declarators (similar to how function_name_node() already walks nested declarator fields) while still capturing @parameters reliably.

Suggested change
(function_definition
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters)) @definition.function
[
(function_definition
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters)) @definition.function
(function_definition
declarator: (pointer_declarator
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters))) @definition.function
(function_definition
declarator: (parenthesized_declarator
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters))) @definition.function
(function_definition
declarator: (pointer_declarator
declarator: (parenthesized_declarator
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters)))) @definition.function
(function_definition
declarator: (parenthesized_declarator
declarator: (pointer_declarator
declarator: (function_declarator
declarator: (_) @name
parameters: (_) @parameters)))) @definition.function
]

Copilot uses AI. Check for mistakes.
…tegration test snapshots

Fix missing else_nodes() for both C and C++ so else-if chains no longer
incorrectly inflate nesting depth and cognitive complexity. Fix
FUNCTION_DECLARATION_QUERY to match pointer-returning functions via
pointer_declarator alternative. Fix C++ call_identifiers returning
(Some("this"), name) for free functions. Move C++ constants to associated
constants and remove dead code. Add basic.stdout snapshot files so
integration tests verify actual analysis output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants