diff --git a/ide/lsp.client/nbproject/project.xml b/ide/lsp.client/nbproject/project.xml index b5bb7c5e5a46..f2ef766bd0dc 100644 --- a/ide/lsp.client/nbproject/project.xml +++ b/ide/lsp.client/nbproject/project.xml @@ -85,6 +85,15 @@ 1.50 + + org.netbeans.core.multiview + + + + 1 + 1.71 + + org.netbeans.libs.flexmark diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/GenericDataObject.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/GenericDataObject.java index c438bebfd16b..9f70924a531a 100644 --- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/GenericDataObject.java +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/GenericDataObject.java @@ -20,9 +20,7 @@ import java.awt.Image; import java.beans.PropertyVetoException; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Method; @@ -30,7 +28,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import javax.imageio.ImageIO; +import org.netbeans.core.spi.multiview.text.MultiViewEditorElement; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataLoaderPool; @@ -41,7 +39,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.util.Exceptions; -import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; /** * @@ -57,7 +55,7 @@ public class GenericDataObject extends MultiDataObject { public GenericDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { super(pf, loader); this.mimeType = FileUtil.getMIMEType(pf); - registerEditor(mimeType, false); + registerEditor(mimeType, true); synchronized (REGISTRY) { REGISTRY.add(new WeakReference<>(this)); } @@ -144,5 +142,8 @@ public static Factory factory() { } }; } -} + public static MultiViewEditorElement createEditor(Lookup lkp) { + return new MultiViewEditorElement(lkp); + } +} \ No newline at end of file diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/LanguageStorage.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/LanguageStorage.java index a00dfde1909b..31d61b38fce0 100644 --- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/LanguageStorage.java +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/options/LanguageStorage.java @@ -33,18 +33,19 @@ import java.util.Set; import java.util.stream.Collectors; import javax.swing.event.ChangeEvent; -import org.eclipse.tm4e.core.registry.IRegistryOptions; -import org.eclipse.tm4e.core.registry.Registry; import org.netbeans.modules.lsp.client.debugger.api.RegisterDAPBreakpoints; import org.eclipse.tm4e.core.internal.grammar.raw.RawGrammarReader; import org.eclipse.tm4e.core.registry.IGrammarSource; +import org.netbeans.core.spi.multiview.MultiViewFactory; import org.netbeans.modules.textmate.lexer.TextmateTokenId; import org.netbeans.spi.navigator.NavigatorPanel; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataLoaderPool; import org.openide.loaders.DataObject; +import org.openide.modules.OnStart; import org.openide.util.Exceptions; +import org.openide.util.NbBundle.Messages; import org.openide.util.NbPreferences; /** @@ -53,6 +54,23 @@ */ public class LanguageStorage { + /** + * Startup handler for language store. This handler reapplies the language + * descriptions at startup so that the runtime view matches the one expected + * by the running IDE. This is mostly relevant when the IDE requires new + * files (like the MultiView description when that feature was introduced). + */ + @OnStart + public static class StartupHandler implements Runnable { + + @Override + public void run() { + // load language definitions and reapply them + store(load()); + } + + } + private static final String KEY = "language.descriptions"; static List load() { @@ -60,6 +78,7 @@ static List load() { return Arrays.stream(new Gson().fromJson(descriptions, LanguageDescription[].class)).collect(Collectors.toList()); } + @Messages("Source=&Source") static void store(List languages) { Set originalMimeTypes = load().stream().map(ld -> ld.mimeType).collect(Collectors.toSet()); Set mimeTypesToClear = new HashSet<>(originalMimeTypes); @@ -74,7 +93,7 @@ static void store(List languages) { Exceptions.printStackTrace(ex); } } - + for (FileObject children : mimeResolver.getChildren()) { if ("synthetic".equals(children.getAttribute(LanguageServersPanel.class.getName()))) { try { @@ -133,6 +152,19 @@ static void store(List languages) { loader.setAttribute("dataObjectClass", GenericDataObject.class.getName()); loader.setAttribute("mimeType", description.mimeType); + deleteConfigFileIfExists("Editors/" + description.mimeType + "/MultiView/source.instance"); + FileObject multiViewRegistration = FileUtil.createData(FileUtil.getConfigRoot(), "Editors/" + description.mimeType + "/MultiView/source.instance"); + Method createMultiViewDescription = MultiViewFactory.class.getDeclaredMethod("createMultiViewDescription", Map.class); + multiViewRegistration.setAttribute("methodvalue:instanceCreate", createMultiViewDescription); + multiViewRegistration.setAttribute("instanceClass", "org.netbeans.core.multiview.ContextAwareDescription"); + multiViewRegistration.setAttribute("class", GenericDataObject.class.getName()); + multiViewRegistration.setAttribute("mimeType", description.mimeType); + multiViewRegistration.setAttribute("displayName", Bundle.Source()); + multiViewRegistration.setAttribute("preferredID", "lsp.source"); + multiViewRegistration.setAttribute("persistenceType", 1); + multiViewRegistration.setAttribute("position", 100); + multiViewRegistration.setAttribute("method", "createEditor"); + FileObject icon = FileUtil.getConfigFile("Loaders/" + description.mimeType + "/Factories/icon.png"); if (icon != null) { icon.delete(); @@ -146,8 +178,9 @@ static void store(List languages) { } loader.setAttribute("iconBase", icon.getNameExt()); + multiViewRegistration.setAttribute("iconBase", icon.getNameExt()); } - + if (description.languageServer != null && !description.languageServer.isEmpty()) { FileObject langServer = FileUtil.createData(FileUtil.getConfigRoot(), "Editors/" + description.mimeType + "/org-netbeans-modules-lsp-client-options-GenericLanguageServer.instance"); langServer.setAttribute("command", description.languageServer.split(" ")); @@ -187,6 +220,7 @@ static void store(List languages) { deleteConfigFileIfExists("Loaders/" + mimeType + "/Factories/data-object.instance"); deleteConfigFileIfExists("Editors/" + mimeType + "/generic-breakpoints.instance"); deleteConfigFileIfExists("Editors/" + mimeType + "/GlyphGutterActions/generic-toggle-breakpoint.shadow"); + deleteConfigFileIfExists("Editors/" + mimeType + "/MultiView/source.instance"); } catch (Exception ex) { Exceptions.printStackTrace(ex); } diff --git a/platform/openide.filesystems/src/org/openide/filesystems/MIMESupport.java b/platform/openide.filesystems/src/org/openide/filesystems/MIMESupport.java index 347fe2c20fba..08c9b5caa805 100644 --- a/platform/openide.filesystems/src/org/openide/filesystems/MIMESupport.java +++ b/platform/openide.filesystems/src/org/openide/filesystems/MIMESupport.java @@ -254,8 +254,8 @@ private static synchronized List declarativeResolvers() { try { // For now, just assume it has the right DTD. Could check this if desired. declmimes.add(MIMEResolverImpl.forDescriptor(f)); // NOI18N - } catch (IOException ex) { - Exceptions.printStackTrace(ex); + } catch (IOException | IllegalArgumentException ex) { + ERR.log(Level.INFO, "Failed to parse declarative MIMEResolver: " + f, ex); } } }