Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endpoints missed by Noir in Java Spring #552

Closed
JohnDuq opened this issue Feb 25, 2025 · 3 comments
Closed

Endpoints missed by Noir in Java Spring #552

JohnDuq opened this issue Feb 25, 2025 · 3 comments
Assignees
Labels
🐞 bug Something isn't working
Milestone

Comments

@JohnDuq
Copy link

JohnDuq commented Feb 25, 2025

Hello NOIR team 👥

I'm using the NOIR app to detect endpoints from Java Spring repositories, but I found that the app is ignoring some endpoints where the Java method has some additional annotations. Maybe this is happening because NOIR finds some additional white spaces 🤔
💡 So I fixed this problem using the following bash script to 'minify' into a single line the annotations before the Java method 💡
Do you have any ideas to avoid the bash process?

Thanks a lot for your replies in advance 😃 🙏 !!!

Original Code:

    @GetMapping(value = "/{id}/thePath")
    @Operation(summary = "Some summary", tags = {"example"},
      responses = {@ApiResponse(content = @Content(schema = @Schema(implementation = Authorization.class)))}
    )
    public ResponseEntity<Object> someMethod(@PathVariable String id) throws SomeException {
    ...

Formatted Code by Bash:

    @GetMapping(value = "/{id}/thePath")
    @Operation(summary = "Some summary", tags = {"example"}, responses = {@ApiResponse(content = @Content(schema = @Schema(implementation = Authorization.class)))})
    public ResponseEntity<Object> someMethod(@PathVariable String id) throws SomeException {
    ...

BASH
How to use?

  1. Copy the bash to root repository as minify_annotations.sh
  2. Run it with ./minify_annotations.sh command

BASH CODE

#!/bin/bash

# Parameters
# $1: Directory to start searching from (default current directory)
# $2: Comma-separated list of annotations (default: "Operation,Auth")
START_DIR=${1:-.}
ANNOTATIONS=${2:-"Operation,Auth"}

# Convert the annotation list to a usable format
IFS=',' read -r -a ANNOTATION_ARRAY <<< "$ANNOTATIONS"

echo "Procesando las siguientes anotaciones: ${ANNOTATIONS}"
echo "Directorio de inicio: ${START_DIR}"

# Function to check if a line starts with any of the specified annotations
starts_with_annotation() {
    local line="$1"
    
    for annotation in "${ANNOTATION_ARRAY[@]}"; do
        if [[ "$line" =~ ^[[:space:]]*@$annotation ]]; then
            echo "$annotation"
            return 0
        fi
    done
    
    echo ""
    return 1
}

# Function to process a Java file
process_file() {
    local file="$1"
    echo "Procesando: $file"
    
    # Temporary file
    local tmpfile=$(mktemp)
    
    # Variables to track whether we are inside an annotation
    local in_annotation=0
    local annotation_text=""
    local unclosed_parentheses=0
    local current_annotation=""
    
    # Read the file line by line and preserve the entire content
    while IFS= read -r line || [[ -n "$line" ]]; do
        # Check if the line starts with any of our annotations
        current_annotation=$(starts_with_annotation "$line")
        
        if [[ -n "$current_annotation" ]]; then
            in_annotation=1
            annotation_text="$line"
            
            # Count open parentheses on this line
            open_count=$(echo "$line" | grep -o "(" | wc -l)
            close_count=$(echo "$line" | grep -o ")" | wc -l)
            unclosed_parentheses=$((open_count - close_count))
            
            # If the annotation ends on the same line
            if [ $unclosed_parentheses -eq 0 ]; then
                # Remove line breaks and excess spaces
                clean_line=$(echo "$annotation_text" | tr -d '\n' | sed 's/[[:space:]]\+/ /g')
                echo "$clean_line" >> "$tmpfile"
                in_annotation=0
            fi
        # Si estamos dentro de una anotación
        elif [ $in_annotation -eq 1 ]; then
            # Remove spaces at the beginning of the line and add it to the accumulated text
            trimmed_line=$(echo "$line" | sed 's/^[[:space:]]*//')
            annotation_text="$annotation_text $trimmed_line"
            
            # Update parentheses count
            open_count=$(echo "$line" | grep -o "(" | wc -l)
            close_count=$(echo "$line" | grep -o ")" | wc -l)
            unclosed_parentheses=$((unclosed_parentheses + open_count - close_count))
            
            # If there are no more unclosed parentheses, we have reached the end of the annotation.
            if [ $unclosed_parentheses -eq 0 ]; then
                # Clean up excess space and format
                clean_line=$(echo "$annotation_text" | tr -d '\n' | sed 's/[[:space:]]\+/ /g')
                
                # Ensure proper spacing after commas
                clean_line=$(echo "$clean_line" | sed 's/,\([^ ]\)/, \1/g')
                
                # Normalize spaces around parentheses and braces, keeping apostrophes
                clean_line=$(echo "$clean_line" | sed 's/( /(/g' | sed 's/ )/)/g' | sed 's/{ /{/g' | sed 's/ }/}/g')
                
                echo "$clean_line" >> "$tmpfile"
                in_annotation=0
            fi
        else
            # If we are not in a note, write the line as is
            echo "$line" >> "$tmpfile"
        fi
    done < "$file"
    
    # Verify that the modified file has content
    if [ -s "$tmpfile" ]; then
        # Check that the keys are balanced in the new file
        open_braces=$(grep -o "{" "$tmpfile" | wc -l)
        close_braces=$(grep -o "}" "$tmpfile" | wc -l)
        
        if [ $open_braces -eq $close_braces ]; then
            # Count how many annotations have been processed
            local processed_count=0
            for annotation in "${ANNOTATION_ARRAY[@]}"; do
                local count=$(grep -c "@$annotation" "$tmpfile")
                processed_count=$((processed_count + count))
            done
            
            # Replace the original file with the modified one
            mv "$tmpfile" "$file"
            echo "Archivo procesado correctamente: $file (encontradas $processed_count anotaciones)"
        else
            echo "ERROR: Las llaves no están balanceadas en el archivo $file. No se aplicaron cambios."
            echo "  Llaves abiertas: $open_braces, Llaves cerradas: $close_braces"
            rm "$tmpfile"
        fi
    else
        echo "ERROR: El archivo temporal está vacío. No se aplicaron cambios a $file."
        rm "$tmpfile"
    fi
}

# Find all .java files and process them
find "$START_DIR" -type f -name "*.java" | while read -r file; do
    process_file "$file"
done

echo "Proceso completado."
@JohnDuq JohnDuq added the 🐞 bug Something isn't working label Feb 25, 2025
@hahwul
Copy link
Member

hahwul commented Feb 26, 2025

@JohnDuq
Hello! Thanks for letting me know!
Noir’s not as detailed as a full compiler, so it can miss some things.

I’ll work on improving it to handle this better. 😊


@ksg97031
Hi, the reported issue is related to Spring, but beyond just fixing this, I think we should consider a broader approach to handling things overall. For now, let’s tackle this issue first and then work on making it more analysis-friendly down the line. How about we discuss it offline?

ksg97031 added a commit that referenced this issue Feb 26, 2025
ksg97031 added a commit that referenced this issue Feb 26, 2025
@ksg97031
Copy link
Member

Hi @JohnDuq,

Thanks for sharing your findings! You're right—there was an issue with parsing Java annotations, especially when they span multiple lines.

I have fixed this issue in the main branch, and it should be deployed in the next version. This means that manually 'minifying' annotations using a bash script should no longer be necessary.

However, if you're still experiencing issues after the next release, please let me know! I'm happy to take another look.

Thanks again for reporting this! 🚀

@hahwul hahwul added this to the v0.20.0 milestone Feb 27, 2025
@hahwul
Copy link
Member

hahwul commented Mar 1, 2025

@JohnDuq cc @ksg97031
v0.20.0 has been released, so this issue is now closed.
If you encounter the same problem again, please feel free to reopen it! Thank you.

@hahwul hahwul closed this as completed Mar 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants