diff options
author | Miguel Costa <miguel.costa@qt.io> | 2023-09-27 16:32:24 +0200 |
---|---|---|
committer | Miguel Costa <miguel.costa@qt.io> | 2024-01-16 10:57:56 +0000 |
commit | 8e192cbe7a90ec57a0ed482ef277915264b124de (patch) | |
tree | 33ca552c9dfea708a9cae10e10e1796c77682fe8 | |
parent | 975ff836028af16080583323f8a12ce9e3df3bf2 (diff) |
Add QML LSP client
Change-Id: Ia833267f8790bcec47cf16c9aa8a53b57c70d954
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r-- | QtVsTools.Core/Options/QtOptionsPage.cs | 72 | ||||
-rw-r--r-- | QtVsTools.Core/VersionInformation.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs | 7 | ||||
-rw-r--r-- | QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs | 13 | ||||
-rw-r--r-- | QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs | 28 | ||||
-rw-r--r-- | QtVsTools.Package/QML/Language/QmlLspClient.cs | 308 | ||||
-rw-r--r-- | QtVsTools.Package/QML/QmlContentType.cs | 31 | ||||
-rw-r--r-- | QtVsTools.Package/QtVsTools.Package.csproj | 3 | ||||
-rw-r--r-- | references.props | 3 |
10 files changed, 439 insertions, 30 deletions
diff --git a/QtVsTools.Core/Options/QtOptionsPage.cs b/QtVsTools.Core/Options/QtOptionsPage.cs index 5ed8aaf8..f9dfd186 100644 --- a/QtVsTools.Core/Options/QtOptionsPage.cs +++ b/QtVsTools.Core/Options/QtOptionsPage.cs @@ -8,6 +8,7 @@ using System.ComponentModel; using System.Globalization; using System.Linq; using System.Linq.Expressions; +using System.IO; using System.Reflection; using Microsoft.Build.Framework; using Microsoft.VisualStudio.Shell; @@ -21,6 +22,7 @@ namespace QtVsTools.Core.Options using VisualStudio; using static Common.Utils; using static QtVsTools.Common.EnumExt; + using static Instances; public static class Options { @@ -87,6 +89,14 @@ namespace QtVsTools.Core.Options [String("LinkNatvis")] Link } + public enum QmlLsp + { + [String("QmlLsp_Enable")] Enable, + [String("QmlLsp_QtVersion")] QtVersion, + [String("QmlLsp_Log")] Log, + [String("QmlLsp_LogSize")] LogSize + } + public enum Timeout : uint { Disabled = 0 } private class TimeoutConverter : EnumConverter @@ -151,6 +161,30 @@ namespace QtVsTools.Core.Options } } + private class QtVersionConverter : StringConverter + { + public override bool GetStandardValuesSupported(ITypeDescriptorContext _) => true; + public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext _) + { + return new(VersionManager.GetVersions() + .Where(IsCompatible) + .Prepend("$(DefaultQtVersion)") + .Cast<object>() + .ToArray()); + } + protected virtual bool IsCompatible(string qtVersion) => true; + } + + private class QmlLspProviderConverter : QtVersionConverter + { + public override bool GetStandardValuesExclusive(ITypeDescriptorContext _) => true; + protected override bool IsCompatible(string qtVersion) + { + return VersionManager.GetVersionInfo(qtVersion) is { } qt + && File.Exists(Path.Combine(qt.LibExecs, "qmlls.exe")); + } + } + [Category("Qt/MSBuild")] [DisplayName("Path to Qt/MSBuild files")] [Description("Corresponds to the QTMSBUILD environment variable")] @@ -261,6 +295,29 @@ namespace QtVsTools.Core.Options [TypeConverter(typeof(EnableDisableConverter))] public bool LinkNatvis { get; set; } + [Category("QML Language Server")] + [DisplayName("Enable")] + [Description("Connect to a QML language server for enhanced code editing experience.")] + [TypeConverter(typeof(EnableDisableConverter))] + public bool QmlLspEnable { get; set; } + + [Category("QML Language Server")] + [DisplayName("Qt Version")] + [Description("Look for a QML language server in the specified Qt installation.")] + [TypeConverter(typeof(QmlLspProviderConverter))] + public string QmlLspVersion { get; set; } + + [Category("QML Language Server")] + [DisplayName("Log")] + [Description("Write exchanged LSP messages to log file in %TEMP%.")] + [TypeConverter(typeof(EnableDisableConverter))] + public bool QmlLspLog { get; set; } + + [Category("QML Language Server")] + [DisplayName("Log Size")] + [Description("Maximum size (in KB) of QML LSP log file.")] + public int QmlLspLogSize { get; set; } + public override void ResetSettings() { ThreadHelper.ThrowIfNotOnUIThread(); @@ -281,6 +338,11 @@ namespace QtVsTools.Core.Options NotifyCMakeConversion = true; LinkNatvis = true; + QmlLspEnable = false; + QmlLspVersion = "$(DefaultQtVersion)"; + QmlLspLog = false; + QmlLspLogSize = 2500; + //////// // Get Qt Help keyboard shortcut // @@ -321,6 +383,10 @@ namespace QtVsTools.Core.Options Load(() => NotifyCMakeConversion, key, Notifications.CMakeConversion); Load(() => UpdateProjectFormat, key, Notifications.UpdateProjectFormat); Load(() => LinkNatvis, key, Natvis.Link); + Load(() => QmlLspEnable, key, QmlLsp.Enable); + Load(() => QmlLspVersion, key, QmlLsp.QtVersion); + Load(() => QmlLspLog, key, QmlLsp.Log); + Load(() => QmlLspLogSize, key, QmlLsp.LogSize); } catch (Exception exception) { exception.Log(); } @@ -336,6 +402,8 @@ namespace QtVsTools.Core.Options Environment.SetEnvironmentVariable( "QTMSBUILD", QtMsBuildPath, EnvironmentVariableTarget.Process); } + if (QmlLspLogSize < 100) + QmlLspLogSize = 100; using var key = Registry.CurrentUser.CreateSubKey(Resources.RegistryPackagePath); if (key == null) @@ -356,6 +424,10 @@ namespace QtVsTools.Core.Options Save(NotifyCMakeConversion, key, Notifications.CMakeConversion); Save(UpdateProjectFormat, key, Notifications.UpdateProjectFormat); Save(LinkNatvis, key, Natvis.Link); + Save(QmlLspEnable, key, QmlLsp.Enable); + Save(QmlLspVersion, key, QmlLsp.QtVersion); + Save(QmlLspLog, key, QmlLsp.Log); + Save(QmlLspLogSize, key, QmlLsp.LogSize); } catch (Exception exception) { exception.Log(); } diff --git a/QtVsTools.Core/VersionInformation.cs b/QtVsTools.Core/VersionInformation.cs index 7ef0bfcc..1a017cd2 100644 --- a/QtVsTools.Core/VersionInformation.cs +++ b/QtVsTools.Core/VersionInformation.cs @@ -262,5 +262,7 @@ namespace QtVsTools.Core } public string InstallPrefix => qmakeQuery["QT_INSTALL_PREFIX"]; + + public string LibExecs => qmakeQuery["QT_INSTALL_LIBEXECS"]; } } diff --git a/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs b/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs index bfbcb84f..b423a66d 100644 --- a/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs @@ -218,9 +218,16 @@ namespace QtVsTools.Qml.Classification string classificationType, ITextView textView, ITextBuffer buffer) + : this(classificationType, buffer) { TextView = textView; textView.Closed += TextView_Closed; + } + + protected QmlAsyncClassifier( + string classificationType, + ITextBuffer buffer) + { Buffer = buffer; buffer.Changed += Buffer_Changed; diff --git a/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs b/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs index d8bff21e..6ae80967 100644 --- a/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs @@ -14,27 +14,26 @@ using Microsoft.VisualStudio.Utilities; namespace QtVsTools.Qml.Classification { - [Export(typeof(IViewTaggerProvider))] - [ContentType("qml")] + [Export(typeof(ITaggerProvider))] + [ContentType(QmlContentType.Name)] [TagType(typeof(ErrorTag))] - internal sealed class QmlErrorClassifierProvider : IViewTaggerProvider + internal sealed class QmlErrorClassifierProvider : ITaggerProvider { [Import] internal IClassificationTypeRegistryService classificationTypeRegistry = null; - public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag + public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag { QmlClassificationType.InitClassificationTypes(classificationTypeRegistry); - return new QmlErrorClassifier(textView, buffer) as ITagger<T>; + return new QmlErrorClassifier(buffer) as ITagger<T>; } } internal sealed class QmlErrorClassifier : QmlAsyncClassifier<ErrorTag> { internal QmlErrorClassifier( - ITextView textView, ITextBuffer buffer) - : base("Error", textView, buffer) + : base("Error", buffer) { } diff --git a/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs b/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs index 04811df7..d474d7d4 100644 --- a/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs @@ -25,7 +25,7 @@ namespace QtVsTools.Qml.Classification using Syntax; [Export(typeof(IViewTaggerProvider))] - [ContentType("qml")] + [ContentType(QmlContentType.Name)] [TagType(typeof(ClassificationTag))] internal sealed class QmlExpressionEvalProvider : IViewTaggerProvider { diff --git a/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs b/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs index 76290c34..c991eea6 100644 --- a/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs @@ -15,42 +15,26 @@ using Microsoft.VisualStudio.Utilities; namespace QtVsTools.Qml.Classification { - [Export(typeof(IViewTaggerProvider))] - [ContentType("qml")] + [Export(typeof(ITaggerProvider))] + [ContentType(QmlContentType.Name)] [TagType(typeof(ClassificationTag))] - internal sealed class QmlSyntaxClassifierProvider : IViewTaggerProvider + internal sealed class QmlSyntaxClassifierProvider : ITaggerProvider { - [Export] - [Name("qml")] - [BaseDefinition("code")] - internal static ContentTypeDefinition qmlContentType = null; - - [Export] - [FileExtension(".qml")] - [ContentType("qml")] - internal static FileExtensionToContentTypeDefinition qmlFileType = null; - - [Export] - [FileExtension(".qmlproject")] - [ContentType("qml")] - internal static FileExtensionToContentTypeDefinition qmlprojectFileType = null; - [Import] internal IClassificationTypeRegistryService classificationTypeRegistry = null; - public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag + public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag { QmlClassificationType.InitClassificationTypes(classificationTypeRegistry); - return new QmlSyntaxClassifier(textView, buffer) as ITagger<T>; + return new QmlSyntaxClassifier(buffer) as ITagger<T>; } } internal sealed class QmlSyntaxClassifier : QmlAsyncClassifier<ClassificationTag> { internal QmlSyntaxClassifier( - ITextView textView, ITextBuffer buffer) - : base("Syntax", textView, buffer) + : base("Syntax", buffer) { } diff --git a/QtVsTools.Package/QML/Language/QmlLspClient.cs b/QtVsTools.Package/QML/Language/QmlLspClient.cs new file mode 100644 index 00000000..3647f2cb --- /dev/null +++ b/QtVsTools.Package/QML/Language/QmlLspClient.cs @@ -0,0 +1,308 @@ +/*************************************************************************************************** + Copyright (C) 2023 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +***************************************************************************************************/ + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Diagnostics; +using System.IO; +using System.IO.Pipes; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.LanguageServer.Client; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Threading; +using Microsoft.VisualStudio.Utilities; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.BraceCompletion; +using Microsoft.VisualStudio.Text.Editor; + +namespace QtVsTools.Qml.Language +{ + using Core; + using static Core.Common.Utils; + using static Instances; + using static Core.Instances; + + [Export(typeof(ILanguageClient))] + [Export(typeof(IBraceCompletionSessionProvider))] + [BracePair('{', '}')] + [ContentType(QmlContentType.Name)] + public class QmlLspClient : + ILanguageClient, + IBraceCompletionSessionProvider + { + public bool TryCreateSession(ITextView textView, SnapshotPoint openingPoint, + char openingBrace, char closingBrace, out IBraceCompletionSession session) + { + session = null; + return true; + } + + public event AsyncEventHandler<EventArgs> StartAsync; + public event AsyncEventHandler<EventArgs> StopAsync; + + public QmlLspClient() + { + } + + public string Name => "QML Language Client"; + + private string PathToQt { get; set; } + private string PathToServer { get; set; } + + private static string LogFilePath { get; } = @$"{Path.GetTempPath()}\qmllsp.log.txt"; + private LogFile Log { get; set; } + + private NamedPipeClientStream StdIn { get; set; } + private NamedPipeClientStream StdOut { get; set; } + private NamedPipeClientStream StdErr { get; set; } + + private Task StdInListner { get; set; } + private Task StdOutListner { get; set; } + private Task StdErrListner { get; set; } + private Task ServerAwaiter { get; set; } + + private Process Server { get; set; } + + public async Task<Connection> ActivateAsync(CancellationToken token) + { + if (!Package.Options.QmlLspEnable) + return null; + + var logMaxSize = 1000 * (Package.Options.QmlLspLogSize switch + { + >= 10 and <= 10000 => Package.Options.QmlLspLogSize, + _ => 2500 + }); + var logTruncSize = 2 * logMaxSize / 3; + + if (PathToServer is not { Length: > 0 }) + return null; + + if (PathToQt is not { Length: > 0 }) + return null; + + if (Server is { HasExited: false }) { + try { + Server.Kill(); + Server.WaitForExit(); + } catch (Exception ex) { + ex.Log(); + } + Server = null; + } + + var server = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = PathToServer, + Arguments = $"-b \"{PathToQt}\"", + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + try { + if (!server.Start()) + return null; + if (token.IsCancellationRequested) { + await StopAsync.InvokeAsync(this, EventArgs.Empty); + await server.WaitForExitAsync(); + return null; + } + } catch (Exception e) { + e.Log(); + return null; + } + + Server = server; + if (Package.Options.QmlLspLog) + return await LogConnectionAsync(server, logMaxSize, logTruncSize); + + return new(server.StandardOutput.BaseStream, server.StandardInput.BaseStream); + } + + public async Task OnLoadedAsync() + { + if (VersionManager is null) + return; + + if (!Package.Options.QmlLspEnable) + return; + var qtVersionName = Package.Options.QmlLspVersion switch + { + { Length: > 0} x when !x.Equals("$(DefaultQtVersion)", IgnoreCase) => x, + _ => VersionManager.GetDefaultVersion() + }; + + if (VersionManager.GetVersionInfo(qtVersionName) is not { } qtVersion) + return; + + var qtPath = qtVersion.InstallPrefix.Replace('/', '\\').TrimEnd('\\'); + if (!Directory.Exists(qtPath)) + return; + + var qmlLsPath = $"{qtVersion.LibExecs.Replace('/', '\\').TrimEnd('\\')}\\qmlls.exe"; + if (!File.Exists(qmlLsPath)) + return; + + PathToQt = qtPath; + PathToServer = qmlLsPath; + + await StartAsync.InvokeAsync(this, EventArgs.Empty); + } + + public async Task OnServerInitializedAsync() + { + await Task.Yield(); + } + + public async Task<InitializationFailureContext> OnServerInitializeFailedAsync( + ILanguageClientInitializationInfo initializationState) + { + await Task.Yield(); + return new InitializationFailureContext + { + FailureMessage = initializationState.StatusMessage + }; + } + + public IEnumerable<string> ConfigurationSections => null; + + public object InitializationOptions => null; + + public IEnumerable<string> FilesToWatch => null; + + public bool ShowNotificationOnInitializeFailed => false; + + private async Task<Connection> LogConnectionAsync(Process server, int size, int truncSize) + { + Log = new(LogFilePath, size, truncSize, "==="); + StdInListner = Task.Run(async () => + { + var data = new byte[4096]; + using var stdIn = new NamedPipeServerStream("qmllsp_stdin", PipeDirection.In); + await stdIn.WaitForConnectionAsync(); + while (!server.HasExited) { + try { + var taskRead = stdIn.ReadAsync(data, 0, data.Length); + var taskWaitForExit = server.WaitForExitAsync(); + await Task.WhenAny(taskRead, taskWaitForExit); + if (!server.HasExited && taskRead.IsCompleted) { + var size = await taskRead; + Log.Write(@$" +CLI <<< SRV [{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] +{Encoding.UTF8.GetString(data, 0, size)} +===".Trim(' ', '\r', '\n') + "\r\n"); + await server.StandardInput.BaseStream.WriteAsync(data, 0, size); + await server.StandardInput.BaseStream.FlushAsync(); + } + } catch (Exception ex) { + ex.Log(); + return; + } + } + }); + + StdOutListner = Task.Run(async () => + { + var data = new byte[4096]; + using var stdOut = new NamedPipeServerStream("qmllsp_stdout", PipeDirection.Out); + await stdOut.WaitForConnectionAsync(); + while (!server.HasExited) { + try { + var taskRead = server.StandardOutput.BaseStream.ReadAsync(data, 0, data.Length); + var taskWaitForExit = server.WaitForExitAsync(); + var completedTask = await Task.WhenAny(taskRead, taskWaitForExit); + if (!server.HasExited && taskRead.IsCompleted) { + var size = await taskRead; + Log.Write(@$" +CLI >>> SRV [{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] +{Encoding.UTF8.GetString(data, 0, size)} +===".Trim(' ', '\r', '\n') + "\r\n"); + await stdOut.WriteAsync(data, 0, size); + await stdOut.FlushAsync(); + } + } catch (Exception ex) { + ex.Log(); + return; + } + } + }); + + StdErrListner = Task.Run(async () => + { + var data = new byte[4096]; + using var stdErr = new NamedPipeServerStream("qmllsp_stderr", PipeDirection.Out); + await stdErr.WaitForConnectionAsync(); + while (!server.HasExited) { + try { + var taskRead = server.StandardError.BaseStream.ReadAsync(data, 0, data.Length); + var taskWaitForExit = server.WaitForExitAsync(); + var completedTask = await Task.WhenAny(taskRead, taskWaitForExit); + if (!server.HasExited && taskRead.IsCompleted) { + var size = await taskRead; + Log.Write(@$" +CLI !!! [{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] +{Encoding.UTF8.GetString(data, 0, size)} +===".Trim(' ', '\r', '\n') + "\r\n"); + await stdErr.WriteAsync(data, 0, size); + await stdErr.FlushAsync(); + } + } catch (Exception ex) { + ex.Log(); + return; + } + } + }); + + StdIn = new NamedPipeClientStream(".", "qmllsp_stdin", PipeDirection.Out); + while (!StdIn.IsConnected) { + try { + await StdIn.ConnectAsync(); + } catch (Exception ex) { + ex.Log(); + await Task.Delay(100); + } + } + + StdOut = new NamedPipeClientStream(".", "qmllsp_stdout", PipeDirection.In); + while (!StdOut.IsConnected) { + try { + await StdOut.ConnectAsync(); + } catch (Exception ex) { + ex.Log(); + await Task.Delay(100); + } + } + + StdErr = new NamedPipeClientStream(".", "qmllsp_stderr", PipeDirection.In); + while (!StdErr.IsConnected) { + try { + await StdErr.ConnectAsync(); + } catch (Exception ex) { + ex.Log(); + await Task.Delay(100); + } + } + + ServerAwaiter = Task.Run(async () => + { + server.WaitForExit(); + await server.WaitForExitAsync(); + StdIn.Dispose(); + StdOut.Dispose(); + StdErr.Dispose(); + }); + + return new(StdOut, StdIn); + } + } +} diff --git a/QtVsTools.Package/QML/QmlContentType.cs b/QtVsTools.Package/QML/QmlContentType.cs new file mode 100644 index 00000000..9ce8dd0f --- /dev/null +++ b/QtVsTools.Package/QML/QmlContentType.cs @@ -0,0 +1,31 @@ +/*************************************************************************************************** + Copyright (C) 2023 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +***************************************************************************************************/ + +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.LanguageServer.Client; +using Microsoft.VisualStudio.Utilities; + +namespace QtVsTools.Qml +{ + internal sealed class QmlContentType + { + public const string Name = "qml"; + + [Export] + [Name(Name)] + [BaseDefinition(CodeRemoteContentDefinition.CodeRemoteContentTypeName)] + internal static ContentTypeDefinition qmlContentType = null; + + [Export] + [FileExtension(".qml")] + [ContentType(Name)] + internal static FileExtensionToContentTypeDefinition qmlFileType = null; + + [Export] + [FileExtension(".qmlproject")] + [ContentType(Name)] + internal static FileExtensionToContentTypeDefinition qmlprojectFileType = null; + } +} diff --git a/QtVsTools.Package/QtVsTools.Package.csproj b/QtVsTools.Package/QtVsTools.Package.csproj index 7d1db0cc..f1df514b 100644 --- a/QtVsTools.Package/QtVsTools.Package.csproj +++ b/QtVsTools.Package/QtVsTools.Package.csproj @@ -94,6 +94,7 @@ <PackageReference Include="$(Name_Microsoft_VisualStudio_Composition)" Version="$(Version_Microsoft_VisualStudio_Composition)" /> <PackageReference Include="$(Name_Microsoft_VisualStudio_Workspace)" Version="$(Version_Microsoft_VisualStudio_Workspace)" /> <PackageReference Include="$(Name_Microsoft_VisualStudio_Workspace_VSIntegration)" Version="$(Version_Microsoft_VisualStudio_Workspace_VSIntegration)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_LanguageServer_Client)" Version="$(Version_Microsoft_VisualStudio_LanguageServer_Client)" /> <PackageReference Include="Community.VisualStudio.VSCT"> <Version>16.0.29.6</Version> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> @@ -320,6 +321,8 @@ <DesignTime>True</DesignTime> <DependentUpon>AssemblyInfo.cs</DependentUpon> </Compile> + <Compile Include="QML\QmlContentType.cs" /> + <Compile Include="QML\Language\QmlLspClient.cs" /> <Compile Include="QtVsToolsPackage.cs" /> <T4Template Include="QtVersionId.vsct_TT"> <Generator>TextTemplatingFileGenerator</Generator> diff --git a/references.props b/references.props index 86f4ed55..494d1b6d 100644 --- a/references.props +++ b/references.props @@ -19,6 +19,7 @@ <Name_Microsoft_VisualStudio_Composition>Microsoft.VisualStudio.Composition</Name_Microsoft_VisualStudio_Composition> <Name_Microsoft_VisualStudio_Workspace>Microsoft.VisualStudio.Workspace</Name_Microsoft_VisualStudio_Workspace> <Name_Microsoft_VisualStudio_Workspace_VSIntegration>Microsoft.VisualStudio.Workspace.VSIntegration</Name_Microsoft_VisualStudio_Workspace_VSIntegration> + <Name_Microsoft_VisualStudio_LanguageServer_Client>Microsoft.VisualStudio.LanguageServer.Client</Name_Microsoft_VisualStudio_LanguageServer_Client> <Name_MSTest_TestAdapter>MSTest.TestAdapter</Name_MSTest_TestAdapter> <Version_MSTest_TestAdapter>2.2.8</Version_MSTest_TestAdapter> @@ -52,6 +53,7 @@ <Version_Microsoft_VisualStudio_Workspace>16.3.43</Version_Microsoft_VisualStudio_Workspace> <Version_Microsoft_VisualStudio_Workspace_VSIntegration>16.3.43</Version_Microsoft_VisualStudio_Workspace_VSIntegration> <Version_Newtonsoft_Json>13.0.1</Version_Newtonsoft_Json> + <Version_Microsoft_VisualStudio_LanguageServer_Client>17.4.1068</Version_Microsoft_VisualStudio_LanguageServer_Client> </PropertyGroup> <!-- // Visual Studio 2019 --> @@ -71,6 +73,7 @@ <Version_Microsoft_VisualStudio_Workspace>16.3.43</Version_Microsoft_VisualStudio_Workspace> <Version_Microsoft_VisualStudio_Workspace_VSIntegration>16.3.43</Version_Microsoft_VisualStudio_Workspace_VSIntegration> <Version_Newtonsoft_Json>12.0.3</Version_Newtonsoft_Json> + <Version_Microsoft_VisualStudio_LanguageServer_Client>16.10.1220</Version_Microsoft_VisualStudio_LanguageServer_Client> </PropertyGroup> </Project> |