1# RUN: rm -rf %t.dir && mkdir -p %t.dir 2 3# The mock driver below is a shell script: 4# REQUIRES: shell 5 6# Create a bin directory to store the mock-driver and add it to the path 7# RUN: mkdir -p %t.dir/bin 8# RUN: export PATH=%t.dir/bin:$PATH 9# Generate a mock-driver that will print %temp_dir%/my/dir and 10# %temp_dir%/my/dir2 as include search paths. 11# RUN: echo '#!/bin/sh' >> %t.dir/bin/my_driver.sh 12# RUN: echo '[ "$0" = "%t.dir/bin/my_driver.sh" ] || exit' >> %t.dir/bin/my_driver.sh 13# RUN: echo '[ "$1" = "-print-file-name=include" ] && echo "%t.dir/builtin" && exit' >> %t.dir/bin/my_driver.sh 14# RUN: echo 'args="$*"' >> %t.dir/bin/my_driver.sh 15# Check that clangd preserves certain flags like `-nostdinc` from 16# original invocation in compile_commands.json. 17# RUN: echo '[ -z "${args##*"-nostdinc"*}" ] || exit' >> %t.dir/bin/my_driver.sh 18# RUN: echo '[ -z "${args##*"--sysroot /my/sysroot/path"*}" ] || exit' >> %t.dir/bin/my_driver.sh 19# RUN: echo '[ -z "${args##*"-isysroot /isysroot"*}" ] || exit' >> %t.dir/bin/my_driver.sh 20# RUN: echo '[ -z "${args##*"-target arm-linux-gnueabihf"*}" ] || exit' >> %t.dir/bin/my_driver.sh 21# RUN: echo '[ -z "${args##*"--stdlib libc++"*}" ] || exit' >> %t.dir/bin/my_driver.sh 22# RUN: echo '[ -z "${args##*"-specs=test.spec"*}" ] || exit' >> %t.dir/bin/my_driver.sh 23# RUN: echo '[ -z "${args##*"--specs=test2.spec"*}" ] || exit' >> %t.dir/bin/my_driver.sh 24# Check that clangd drops other flags like -lc++, which don't affect includes 25# RUN: echo '[ -n "${args##*"-lc++"*}" ] || exit' >> %t.dir/bin/my_driver.sh 26# RUN: echo 'echo line to ignore >&2' >> %t.dir/bin/my_driver.sh 27# RUN: echo 'printf "Target: arm-linux-gnueabihf\r\n" >&2' >> %t.dir/bin/my_driver.sh 28# RUN: echo 'printf "#include <...> search starts here:\r\n" >&2' >> %t.dir/bin/my_driver.sh 29# RUN: echo 'echo %t.dir/my/dir/ >&2' >> %t.dir/bin/my_driver.sh 30# RUN: echo 'echo %t.dir/my/dir2/ >&2' >> %t.dir/bin/my_driver.sh 31# RUN: echo 'echo %t.dir/builtin >&2' >> %t.dir/bin/my_driver.sh 32# RUN: echo 'printf "End of search list.\r\n" >&2' >> %t.dir/bin/my_driver.sh 33# RUN: chmod +x %t.dir/bin/my_driver.sh 34 35# Create header files my/dir/a.h and my/dir2/b.h 36# RUN: mkdir -p %t.dir/my/dir 37# RUN: touch %t.dir/my/dir/a.h 38# RUN: mkdir -p %t.dir/my/dir2 39# RUN: touch %t.dir/my/dir2/b.h 40# RUN: mkdir -p %t.dir/builtin 41# RUN: touch %t.dir/builtin/c.h 42 43# Generate a compile_commands.json that will query the mock driver we've 44# created. Which should add a.h and b.h into include search path. 45# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp --target=arm-linux-gnueabihf -nostdinc --sysroot /my/sysroot/path -isysroot/isysroot -stdlib=libc++ -lc++ -specs=test.spec --specs=test2.spec", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json 46 47# RUN: sed -e "s|INPUT_DIR|%/t.dir|g" %s > %t.test.1 48# On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..." 49# (with the extra slash in the front), so we add it here. 50# RUN: sed -E -e 's|"file://([A-Z]):/|"file:///\1:/|g' %t.test.1 > %t.test 51 52# Bless the mock driver we've just created so that clangd can execute it. 53# Note: include clangd's stderr in the FileCheck input with "2>&1" so that we 54# can match output lines like "ASTWorker building file" 55# RUN: clangd -lit-test -query-driver="**.test,**.sh" < %t.test 2>&1 | FileCheck -strict-whitespace %t.test 56{"jsonrpc":"2.0","id":0,"method":"initialize","params":{}} 57--- 58{ 59 "jsonrpc":"2.0", 60 "method":"textDocument/didOpen", 61 "params": { 62 "textDocument": { 63 "uri": "file://INPUT_DIR/the-file.cpp", 64 "languageId":"cpp", 65 "version":1, 66 "text":"#include <a.h>\n#include <b.h>\n#if !defined(__ARM_ARCH) || !defined(__gnu_linux__)\n#error \"Invalid target\"\n#endif\n#if __has_include(<c.h>)\n#error \"wrong-toolchain builtins\"\n#endif\n" 67 } 68 } 69} 70# Look for the "ASTWorker building file" line so that the subsequent diagnostics 71# that are matches are for the C++ source file and not a config file. 72# CHECK: ASTWorker building file 73# CHECK: "method": "textDocument/publishDiagnostics", 74# CHECK-NEXT: "params": { 75# CHECK-NEXT: "diagnostics": [], 76# CHECK-NEXT: "uri": "file://{{.*}}/the-file.cpp", 77--- 78{"jsonrpc":"2.0","id":10000,"method":"shutdown"} 79--- 80{"jsonrpc":"2.0","method":"exit"} 81 82# Generate a different compile_commands.json which does not point to the mock driver 83# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp --target=arm-linux-gnueabihf -nostdinc --sysroot /my/sysroot/path -isysroot/isysroot -stdlib=libc++ -lc++ -specs=test.spec --specs=test2.spec", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json 84 85# Generate a clangd config file which points to the mock driver instead 86# RUN: echo 'CompileFlags:' > %t.dir/.clangd 87# RUN: echo ' Compiler: my_driver.sh' >> %t.dir/.clangd 88 89# Run clangd a second time, to make sure it picks up the driver name from the config file 90# Note, we need to pass -enable-config because -lit-test otherwise disables it 91# RUN: clangd -lit-test -enable-config -query-driver="**.test,**.sh" < %t.test 2>&1 | FileCheck -strict-whitespace %t.test 92