Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ It has been tested with:
|:----------------------------------|:---------------:|:------------------:|
| Syntax Highlighting | ✅ | ✅ |
| Code Snippets | ✅ | ✅ |
| Live Template Analysis | ✅ | ✅ |
| Live Template Analysis | ✅ | ✅ |
| HTML Language Features | ✅ | - |
| ViewHelper Autocomplete (tags) | *only built-in* | - |
| ViewHelper Documentation (tags) | *only built-in* | - |
Expand All @@ -35,9 +35,13 @@ It has been tested with:
### Live Template Analysis

The extension is able to utilize available binaries in your project to provide live
template analysis for Fluid templates, e. g. for detecting syntax errors or deprecations.
This works out-of-the-box for Fluid 5.3 (or higher) and TYPO3 14.3 (or higher). The
following folders are checked for the `fluid` and `typo3` binaries:
template analysis for Fluid templates, e. g. to detect syntax errors or deprecations.
This works out-of-the-box for Fluid 5.3 (or higher) and TYPO3 14.3 (or higher). In older
TYPO3 versions the
[companion extension](https://extensions.typo3.org/extension/fluid_companion) needs to
be installed.

The following folders are checked for the `fluid` and `typo3` binaries:

* `vendor/bin/`
* `bin/`
Expand All @@ -54,9 +58,6 @@ Custom paths to the binaries can also be specified in the extension's configurat
path of the current workplace folder. Apart from that, these are currently **not**
preprocessed, so be extra careful.

Compatibility with older versions of TYPO3 might still be feasible, but this is not
implemented yet.

### ViewHelper Autocomplete & Documentation

The extension currently doesn't include a dedicated
Expand Down
90 changes: 90 additions & 0 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,50 @@ const updateDiagnostics = debounce((document: TextDocument, collection: Diagnost
if (!analyzeResult) {
collection.delete(document.uri);
if (analyzeResult === false) {
const typo3Version = detectTypo3Version(document);
if (typo3Version === 12 || typo3Version === 13) {
vscode.window.showInformationMessage(
`To be able to provide live analysis for Fluid templates in TYPO3 ${typo3Version}, a companion TYPO3 extension needs to be installed.`,
{ identifier: 'more', title: 'Learn more' },
{ identifier: 'disable', title: 'Disable for workspace' },
).then(userOption => {
switch (userOption?.identifier) {
case 'more':
vscode.env.openExternal(
vscode.Uri.parse('https://extensions.typo3.org/extension/fluid_companion'),
);
break;

case 'disable':
vscode.workspace.getConfiguration('fluid.features').update(
'liveTemplateAnalysis',
false,
vscode.ConfigurationTarget.Workspace
);
break;
}
});
return;
}

if (typo3Version && typo3Version < 12) {
vscode.window.showInformationMessage(
`Live analysis for Fluid templates is not compatible with TYPO3 ${typo3Version}.`,
{ identifier: 'disable', title: 'Disable for workspace' },
).then(userOption => {
switch (userOption?.identifier) {
case 'disable':
vscode.workspace.getConfiguration('fluid.features').update(
'liveTemplateAnalysis',
false,
vscode.ConfigurationTarget.Workspace
);
break;
}
});
return;
}

logChannel.info('Try increasing the log level to "debug" to get more information about the issue.');
vscode.window.showInformationMessage(
'Unable to provide live analysis for Fluid templates in this workspace.',
Expand Down Expand Up @@ -211,6 +255,52 @@ function analyzeTemplate(document: TextDocument): TemplateValidatorResult|null|f
return false;
}

function detectTypo3Version(document: TextDocument): number|null
{
const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri)?.uri.fsPath;
if (!workspaceFolder) {
return null;
}

// Go through binary alternatives to find the best candidate
const candidates: BinaryCommand[] = [];
const isDdevProject = config.bin.useDdevIfAvailable ? fs.existsSync(path.join(workspaceFolder, '.ddev')) : false;
const ddev = isDdevProject ? spawnSync('which', ['ddev'], { shell: true }).stdout.toString().trim() : '';

// TODO optimize this to avoid duplicate calls to non-existent binaries
if (config.bin.typo3) {
candidates.push({
command: config.bin.typo3.replaceAll('${workspaceFolder}', workspaceFolder),
args: ['--version'],
userDefined: true,
});
}
if (isDdevProject && ddev) {
candidates.push({
command: ddev,
args: ['typo3', '--version'],
});
}
for (const typo3Binary of ['vendor/bin/typo3', 'bin/typo3', '.Build/bin/typo3']) {
candidates.push({
command: path.join(workspaceFolder, typo3Binary),
args: ['--version'],
});
}
for (const candidate of candidates) {
const process = spawnSync(candidate.command, candidate.args);
if (!process.stdout) {
continue;
}
const versionOutput = process.stdout?.toString() ?? '';
const versionMatch = versionOutput.match(/TYPO3 CMS ([0-9]+)\.[0-9]+\.[0-9]+/);
if (versionMatch && versionMatch[1]) {
return Number(versionMatch[1]);
}
}
return null;
}

function tryAndVerifyAnalyzeCommand(command: BinaryCommand, input: string, cwd: string): TemplateValidatorResult|null {
const readableCommand = [command.command, ...command.args].join(' ');
let rawResult, rawError, errorCode;
Expand Down