Using semgrep in vim
In this post, I want to share my workflow for harnessing the power of Semgrep in Vim. Semgrep, a robust code analysis tool, can significantly enhance your codebase investigation process. Let me take you through my method for optimizing and simplifying code pattern searches effectively within Neovim.
My approach to using Semgrep is rather straightforward. I execute Semgrep from the command line to search for specific code patterns. For instance, you can look for a pattern in a Go codebase like this:
semgrep --quiet --lang=go --pattern="func min(...)"
My Refined Workflow
Here's the step-by-step approach I've refined for maximizing Semgrep's capabilities:
- Pattern Configuration: I begin by configuring the code pattern directly in a dedicated file, typically named semgrep_rule.yml.
- Running Semgrep: After configuring the pattern, I save the configuration file and execute Semgrep to initiate the code search.
- Loading Results in Neovim: Once Semgrep completes its search, I promptly load the results directly into Neovim for in-depth investigation.
To streamline this process, I've created a convenient script. It's worth noting that I use a random name for added flexibility when working on multiple sessions:
function run_semgrep() {
# Generate a random string for file name
random_value=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)
# Create a temporary config file with a random value and a .yaml prefix
config_tempfile="/tmp/config.${random_value}.yaml"
# Copy the content of ~/.semgrep/config.yml to the temporary config file
cp ~/.semgrep/config.yml "$config_tempfile"
echo "Make config file $config_tempfile"
# Open the temporary config file in nvim for editing
nvim "$config_tempfile"
# Create a temporary output file with a random value
output_tempfile="/tmp/output.${random_value}.txt"
# After closing nvim, execute semgrep
echo 'Running semgrep .. Please wait'
semgrep --vim -f $config_tempfile --output $output_tempfile
# Check if the output file is not empty
if [ -s "$output_tempfile" ]; then
# Open the output tempfile with nvim
nvim -c ":cfile $output_tempfile"
fi
# Clean up the temporary files
echo "Clean up ... $config_tempfile"
echo "Clean up ... $output_tempfile"
rm "$config_tempfile"
rm "$output_tempfile"
}
Here's an example configuration for finding structs that contain a function as a field:
rules:
- id: find-field-func
patterns:
- pattern: |
type $T struct {
$FIELD func(...) $RESULT
}
message: Semgrep found matches
languages:
- go
severity: WARNING
To make my life easier, I've created an alias:
alias sg="run_semgrep"
In summary, this workflow eliminates the need for manual codebase investigation, making my development process significantly more efficient.