diff --git a/server/src/__tests__/embedded-languages.test.ts b/server/src/__tests__/embedded-languages.test.ts index a1e69771..4c7e173d 100644 --- a/server/src/__tests__/embedded-languages.test.ts +++ b/server/src/__tests__/embedded-languages.test.ts @@ -32,6 +32,12 @@ describe('Create basic embedded bash documents', () => { 'with override', 'foo:append(){\nBAR=""\n}', `${shebang}foo (){\nBAR=""\n}` + ], + [ + 'with inline python', + // eslint-disable-next-line no-template-curly-in-string + 'foo(){\n${@FOO}\n}', + `${shebang}foo(){\n\${? }\n}` ] ])('%s', async (description, input, result) => { const embeddedContent = await createEmbeddedContent(input, 'bash') @@ -114,14 +120,13 @@ describe('Create Python embedded language content with inline Python', () => { // eslint-disable-next-line no-template-curly-in-string 'inherit ${@"test"}', `${imports} \n\n"test"\n` - ] - /* // This is not yet supported by tree-sitter + ], [ 'inside bash function', // eslint-disable-next-line no-template-curly-in-string - 'foo(){\necho ${@"bar"}\n}\n', - ' \n \n"bar"\n\n \n' - ] */ + 'foo(){\n${@FOO}\n}', + `${imports} \n \n\nFOO\n\n ` + ] ])('%s', async (description, input, result) => { const embeddedContent = await createEmbeddedContent(input, 'python') expect(embeddedContent).toEqual(result) diff --git a/server/src/embedded-languages/bash-support.ts b/server/src/embedded-languages/bash-support.ts index d8501ddf..d79f1a00 100644 --- a/server/src/embedded-languages/bash-support.ts +++ b/server/src/embedded-languages/bash-support.ts @@ -8,6 +8,7 @@ import * as TreeSitterUtils from '../tree-sitter/utils' import { initEmbeddedLanguageDoc, insertTextIntoEmbeddedLanguageDoc } from './utils' import { type EmbeddedLanguageDoc } from '../lib/src/types/embedded-languages' import { type SyntaxNode } from 'web-tree-sitter' +import { logger } from '../lib/src/utils/OutputLogger' export const shebang = '#!/bin/sh\n' @@ -35,12 +36,33 @@ const handleFunctionDefinitionNode = (node: SyntaxNode, embeddedLanguageDoc: Emb case 'override': handleOverrideNode(child, embeddedLanguageDoc) break + case 'inline_python': + handleInlinePythonNode(child, embeddedLanguageDoc) + break default: break } }) } +const handleInlinePythonNode = (inlinePythonNode: SyntaxNode, embeddedLanguageDoc: EmbeddedLanguageDoc): void => { + // Example: + // if [ "${@d.getVar('FOO')}" = "0" ] ; + // will become + // if [ "${? }" = "0" ] ; + // Replacing the whole inline_python by spaces would create a constant string and might trigger a warning if the spellcheck + // extension is activated, since the comparison with "0" would always give the same result + // ${?} is an arbitrary value that is expected not to cause any trouble. + const trailingSpacesLength = inlinePythonNode.text.length - 4 + if (trailingSpacesLength <= 0) { + // This is expected to never happen + logger.error(`[handleInlinePythonNode (Bash)] Invalid string length for node ${inlinePythonNode.toString()}`) + return + } + const replacement = `\${?${' '.repeat(trailingSpacesLength)}}` + insertTextIntoEmbeddedLanguageDoc(embeddedLanguageDoc, inlinePythonNode.startIndex, inlinePythonNode.endIndex, replacement) +} + const handleOverrideNode = (overrideNode: SyntaxNode, embeddedLanguageDoc: EmbeddedLanguageDoc): void => { // Remove it insertTextIntoEmbeddedLanguageDoc(embeddedLanguageDoc, overrideNode.startIndex, overrideNode.endIndex, ' '.repeat(overrideNode.text.length))