#! /usr/bin/env bash
#
# Build and test support for a language
#
set -eu -o pipefail

prog_name=$(basename "$0")

usage() {
  cat <<EOF
Build and test support for a language. For example,

  ./$prog_name typescript

will take care of rebuilding and testing the components for the sublanguages
'typescript' and 'tsx' whose original grammars are defined in the
'tree-sitter-typescript' project.

Usage: $prog_name LANG
Options:
  --help
      Print this message and exit.
EOF
}

error() {
  echo "Error in '$prog_name': $*" >&2
  exit 1
}

lang=''

while [[ $# -gt 0 ]]; do
  case "$1" in
    --help)
      usage
      exit 0
      ;;
    *)
      if [[ -n "$lang" ]]; then
        error "Exactly one language must be specified on the command line"
      fi
      lang="$1"
  esac
  shift
done

if [[ -z "$lang" ]]; then
  error "Missing language name."
fi

echo "Building the extended parser semgrep-$lang."
(
  cd semgrep-grammars/src/semgrep-"$lang"
  make clean
  make test
)

sublangs="$(python3 ../scripts/grammar_registry.py test-sublangs "$lang")"

check_for_blanks() {
  cst_ml=ocaml-src/lib/CST.ml
  # Emit one BLANK-NODE <sublanguage> <CST type> record per occurrence.
  # Update tooling compares these counts with the pre-bump baseline to catch
  # new token/location loss without rejecting existing Blank nodes.
  awk -v lang="$sublang" '
    /^(type|and) / { node = $2 }
    {
      rest = $0
      while (match(rest, /(^|[^[:alnum:]_])Blank([^[:alnum:]_]|$)/)) {
        print "BLANK-NODE " lang " " node
        rest = substr(rest, RSTART + RLENGTH - 1)
      }
    }
  ' "$cst_ml"
  if grep -C 2 '\bBlank\b' "$cst_ml"; then
    cat 2>&1 <<EOF

found in $(pwd)/$cst_ml
language: $sublang

*** Warning: We have some Blank nodes, which will produce no tokens. ***

This means there won't be any token or location information available
at parsing time for these nodes.

You should get back to the grammar and create named rules for these nodes
to avoid this problem.
EOF
    else
      echo "$sublang: OK"
  fi
}

echo "Testing C/OCaml code generation for sublanguages: $sublangs"
for sublang in $sublangs; do
  (
    cd "$sublang"
    make clean
    make test
  )
done

for sublang in $sublangs; do
  (
    echo "$sublang: Checking for undesirable Blank nodes."
    cd "$sublang"
    check_for_blanks
  )
done
