Skip to content

feat: smartcase match workspace/symbol query - #884

Merged
CppCXY merged 1 commit into
EmmyLuaLs:mainfrom
phanen:ws-sym-match
Dec 18, 2025
Merged

CppCXY merged 1 commit into
EmmyLuaLs:mainfrom
phanen:ws-sym-match

Conversation

@phanen

@phanen phanen commented Dec 13, 2025

Copy link
Copy Markdown
Contributor

if query contains uppercase, do case-sensitive match; otherwise, ignore case

if query contains uppercase, do case-sensitive match; otherwise, ignore
case
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @phanen, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the workspace symbol search functionality by introducing a 'smartcase' matching mechanism. This improvement allows users to perform more intuitive searches: queries containing uppercase letters will trigger a case-sensitive match, while queries composed entirely of lowercase letters will result in a case-insensitive match. This change aims to provide a more flexible and user-friendly search experience for workspace symbols.

Highlights

  • Smartcase Matching Logic: A new private function, match_symbol, has been introduced to implement the smartcase matching logic. This function checks if the query contains any uppercase characters; if so, it performs a case-sensitive substring match. Otherwise, it performs a case-insensitive match by converting both the text and query to lowercase.
  • Global Variable Symbol Search: The add_global_variable_symbols function now utilizes the new match_symbol logic, applying smartcase matching when filtering global variable names based on the user's query.
  • Type Symbol Search: The add_type_symbols function has been updated to use the match_symbol function, enabling smartcase matching for type full names during workspace symbol queries.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a 'smart case' matching for workspace symbol search, which is a great feature. The implementation is straightforward. I've left one comment with a suggestion to refactor the matching logic for better performance and to avoid redundant computations within loops. This involves creating a small helper struct to manage the query state.

Comment on lines +6 to +12
fn match_symbol(text: &str, query: &str) -> bool {
if query.chars().any(|c| c.is_uppercase()) {
text.contains(query)
} else {
text.to_lowercase().contains(&query.to_lowercase())
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This function is called inside loops in add_global_variable_symbols and add_type_symbols. This means that query.chars().any(|c| c.is_uppercase()) and query.to_lowercase() are executed on every iteration, which is inefficient as the query does not change inside the loops.

Additionally, text.to_lowercase() allocates a new string on every call in the case-insensitive branch, which could impact performance when searching through many symbols.

To improve this, I suggest introducing a struct that pre-processes the query. This avoids redundant work inside the loops and encapsulates the matching logic cleanly. Here's a possible refactoring:

First, you could define a SymbolMatcher struct to replace match_symbol:

struct SymbolMatcher {
    query: String,
    query_lower: String,
    case_sensitive: bool,
}

impl SymbolMatcher {
    fn new(query: String) -> Self {
        let case_sensitive = query.chars().any(|c| c.is_uppercase());
        let query_lower = if case_sensitive { String::new() } else { query.to_lowercase() };
        Self { query, query_lower, case_sensitive }
    }

    fn is_match(&self, text: &str) -> bool {
        if self.case_sensitive {
            text.contains(&self.query)
        } else {
            // Note: text.to_lowercase() still allocates. For further optimization,
            // a custom case-insensitive search or a crate like `caseless` could be used.
            text.to_lowercase().contains(&self.query_lower)
        }
    }
}

Then, you would use it in build_workspace_symbols and pass the matcher to the other functions:

// In build_workspace_symbols
let matcher = SymbolMatcher::new(query);
add_global_variable_symbols(&mut symbols, compilation, &matcher, &cancel_token)?;
add_type_symbols(&mut symbols, compilation, &matcher, &cancel_token)?;

// In add_global_variable_symbols (signature changed to accept &SymbolMatcher)
if matcher.is_match(decl.get_name()) {
    // ...
}

This refactoring would make the matching logic more efficient by processing the query only once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this AI modification makes a lot of sense.

@CppCXY
CppCXY merged commit cc19690 into EmmyLuaLs:main Dec 18, 2025
22 checks passed
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