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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
Expand Down Expand Up @@ -66,6 +67,13 @@ protected PsiFile createExpressionCodeFragment(@NotNull Project project,
// Get file type / language of the file which is debugging when debugger is suspended.
fileType = file.getFileType();
language = file.getLanguage();
// If the file's language is a more specific dialect of the file type's language, degrade to the file type's
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main logic change for the fix. It basically does what's described in the PR itself.

if (fileType instanceof LanguageFileType languageFileType) {
Language fileTypeLanguage = languageFileType.getLanguage();
if (!language.is(fileTypeLanguage) && language.isKindOf(fileTypeLanguage)) {
language = fileTypeLanguage;
}
}
}
return createExpressionCodeFragment(project, text, fileType, language);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2026 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/

package com.redhat.devtools.lsp4ij.dap;

import com.intellij.json.JsonFileType;
import com.intellij.json.JsonLanguage;
import com.intellij.json.json5.Json5Language;
import com.intellij.openapi.fileTypes.MockLanguageFileType;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.testFramework.LightVirtualFile;

public class DAPDebuggerEditorsProviderTest extends LightPlatformTestCase {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests to verify the original behavior for simple file types with a single language and the corrected behavior for more complex file types that can have multiple dialects of a language.


public void testWithSimpleLanguage() {
PsiFile textFile = createFile("test.txt", "Hello, world.");
assertEquals(PlainTextFileType.INSTANCE, textFile.getFileType());
assertEquals(PlainTextLanguage.INSTANCE, textFile.getLanguage());

DAPDebuggerEditorsProvider debuggerEditorsProvider = new DAPDebuggerEditorsProvider(PlainTextFileType.INSTANCE, null);

PsiFile codeFragment = debuggerEditorsProvider.createExpressionCodeFragment(getProject(), "", textFile, true);
assertEquals(PlainTextFileType.INSTANCE, codeFragment.getFileType());
assertEquals(PlainTextLanguage.INSTANCE, codeFragment.getLanguage());
}

public void testWithDialectLanguage() {
Copy link
Copy Markdown
Contributor Author

@SCWells72 SCWells72 Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use JSON here because it already has a JSON5 dialect/variant, though it still operates differently than the JavaScript ones because for JSON, there's a 1:1 correspondence between file types (JsonFileType and Json5FileType) and languages (JsonLanguage and Json5Language) whereas for JavaScript, there's a single JavaScriptFileType for all of the languages/dialects. So using JSON almost gets me to a reproduction, but there's one thing I have to do explicitly in this test to model the JavaScript behavior.

// Create a file with the dialect language
PsiFile dialectFile = PsiFileFactory.getInstance(getProject()).createFileFromText("test.json", Json5Language.INSTANCE, "{}");
VirtualFile dialectVirtualFile = dialectFile.getVirtualFile();
// Force the file type to be the base instead of the one inferred from the dialect language used above
Copy link
Copy Markdown
Contributor Author

@SCWells72 SCWells72 Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And that one thing is right here. At this point, the file type of dialectFile is Json5FileType, inferred from Json5Language used when creating the file. That won't reproduce the original behavior/issue, though, but thankfully I can set the file type explicitly on the underlying LightVirtualFile so that it does in fact model the JavaScript-like behavior of a single file type that can have multiple languages, all but one of which don't match the file type's own reported language.

((LightVirtualFile) dialectVirtualFile).setFileType(JsonFileType.INSTANCE);
assertEquals(JsonFileType.INSTANCE, dialectFile.getFileType());
assertEquals(Json5Language.INSTANCE, dialectFile.getLanguage());

// This should also use the base file type
DAPDebuggerEditorsProvider debuggerEditorsProvider = new DAPDebuggerEditorsProvider(MockLanguageFileType.INSTANCE, null);

// If the original issue exists, this will fail with "JSON5 doesn't participate in view provider..."
PsiFile codeFragment = debuggerEditorsProvider.createExpressionCodeFragment(getProject(), "", dialectFile, true);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated above, without the fix in this PR, this line will fail with the exact error/stack trace reported in #1118 and #1465. With the fix, the code fragment is created successfully with the dialect's base language.

assertEquals(JsonFileType.INSTANCE, codeFragment.getFileType());
// It should have degraded to the base language
assertEquals(JsonLanguage.INSTANCE, codeFragment.getLanguage());
}
}
Loading