@@ -7,8 +7,15 @@ import SelectorHandler from './selector';
77import getCoursierExecutable from './coursier/coursier' ;
88
99let client : lsp . LanguageClient ;
10+ let versionStatusBarItem : vscode . StatusBarItem ;
11+
12+ const VERSION_POLICY_PROMPTED_KEY = 'smithy.versionPolicyPrompted' ;
13+ const LATEST_RELEASE = 'latest.release' ;
1014
1115export async function activate ( context : vscode . ExtensionContext ) {
16+ await promptVersionPolicy ( context ) ;
17+ createVersionStatusBarItem ( context ) ;
18+
1219 const server = await getServer ( context ) ;
1320 const clientOptions = getClientOptions ( ) ;
1421
@@ -21,7 +28,8 @@ export async function activate(context: vscode.ExtensionContext) {
2128 context . subscriptions . push (
2229 vscode . workspace . registerTextDocumentContentProvider ( 'smithyjar' , jarFileContentsProvider ) ,
2330 vscode . commands . registerCommand ( 'smithy.runSelector' , selectorHandler . run , selectorHandler ) ,
24- vscode . commands . registerCommand ( 'smithy.clearSelector' , selectorHandler . clear , selectorHandler )
31+ vscode . commands . registerCommand ( 'smithy.clearSelector' , selectorHandler . clear , selectorHandler ) ,
32+ vscode . commands . registerCommand ( 'smithy.toggleVersionPolicy' , ( ) => toggleVersionPolicy ( context ) )
2533 ) ;
2634
2735 // Start the client. This will also launch the server
@@ -35,6 +43,117 @@ export function deactivate(): Thenable<void> | undefined {
3543 return client . stop ( ) ;
3644}
3745
46+ async function promptVersionPolicy ( context : vscode . ExtensionContext ) : Promise < void > {
47+ if ( context . globalState . get < boolean > ( VERSION_POLICY_PROMPTED_KEY ) ) {
48+ return ;
49+ }
50+
51+ const useLatest = 'Use latest' ;
52+ const pinVersion = 'Pin a version' ;
53+ const choice = await vscode . window . showInformationMessage (
54+ 'The Smithy extension can automatically use the latest Smithy Language Server, or you can pin a specific version.' ,
55+ useLatest ,
56+ pinVersion
57+ ) ;
58+
59+ await context . globalState . update ( VERSION_POLICY_PROMPTED_KEY , true ) ;
60+
61+ if ( choice === pinVersion ) {
62+ await pickAndPinVersion ( ) ;
63+ }
64+ }
65+
66+ function createVersionStatusBarItem ( context : vscode . ExtensionContext ) : void {
67+ versionStatusBarItem = vscode . window . createStatusBarItem ( vscode . StatusBarAlignment . Right , 100 ) ;
68+ versionStatusBarItem . command = 'smithy.toggleVersionPolicy' ;
69+ updateVersionStatusBarItem ( ) ;
70+ versionStatusBarItem . show ( ) ;
71+ context . subscriptions . push ( versionStatusBarItem ) ;
72+
73+ // Update status bar when configuration changes
74+ context . subscriptions . push (
75+ vscode . workspace . onDidChangeConfiguration ( ( e ) => {
76+ if ( e . affectsConfiguration ( 'smithy.server.version' ) ) {
77+ updateVersionStatusBarItem ( ) ;
78+ }
79+ } )
80+ ) ;
81+ }
82+
83+ function updateVersionStatusBarItem ( ) : void {
84+ const version = config . getServerVersion ( ) ;
85+ if ( version === LATEST_RELEASE ) {
86+ versionStatusBarItem . text = '$(check) Smithy LS (latest)' ;
87+ versionStatusBarItem . tooltip =
88+ 'Smithy Language Server: using latest from Maven Central. Click to pin a version.' ;
89+ } else {
90+ versionStatusBarItem . text = '$(pin) Smithy LS v' + version ;
91+ versionStatusBarItem . tooltip = 'Smithy Language Server: pinned to v' + version + '. Click to switch to latest.' ;
92+ }
93+ }
94+
95+ async function fetchAvailableVersions ( ) : Promise < string [ ] > {
96+ const metadataUrl =
97+ 'https://repo1.maven.org/maven2/software/amazon/smithy/smithy-language-server/maven-metadata.xml' ;
98+ try {
99+ const response = await fetch ( metadataUrl ) ;
100+ const text = await response . text ( ) ;
101+ const versions = [ ...text . matchAll ( / < v e r s i o n > ( [ ^ < ] + ) < \/ v e r s i o n > / g) ] . map ( ( m ) => m [ 1 ] ) . reverse ( ) ;
102+ return versions ;
103+ } catch {
104+ return [ ] ;
105+ }
106+ }
107+
108+ async function pickAndPinVersion ( ) : Promise < void > {
109+ const versions = await vscode . window . withProgress (
110+ { location : vscode . ProgressLocation . Notification , title : 'Fetching available versions...' } ,
111+ ( ) => fetchAvailableVersions ( )
112+ ) ;
113+
114+ if ( versions . length === 0 ) {
115+ vscode . window . showErrorMessage ( 'Could not fetch Smithy Language Server versions from Maven Central.' ) ;
116+ return ;
117+ }
118+
119+ const picked = await vscode . window . showQuickPick ( versions , {
120+ placeHolder : 'Select a Smithy Language Server version to pin' ,
121+ } ) ;
122+
123+ if ( picked ) {
124+ await vscode . workspace
125+ . getConfiguration ( 'smithy' )
126+ . update ( 'server.version' , picked , vscode . ConfigurationTarget . Global ) ;
127+ const reload = await vscode . window . showInformationMessage (
128+ 'Smithy Language Server pinned to v' + picked + '. Reload window to apply.' ,
129+ 'Reload'
130+ ) ;
131+ if ( reload === 'Reload' ) {
132+ vscode . commands . executeCommand ( 'workbench.action.reloadWindow' ) ;
133+ }
134+ }
135+ }
136+
137+ async function toggleVersionPolicy ( context : vscode . ExtensionContext ) : Promise < void > {
138+ const currentVersion = config . getServerVersion ( ) ;
139+ const isLatest = currentVersion === LATEST_RELEASE ;
140+
141+ if ( isLatest ) {
142+ await pickAndPinVersion ( ) ;
143+ } else {
144+ await vscode . workspace
145+ . getConfiguration ( 'smithy' )
146+ . update ( 'server.version' , undefined , vscode . ConfigurationTarget . Global ) ;
147+ const reload = await vscode . window . showInformationMessage (
148+ 'Smithy Language Server set to use latest version. Reload window to apply.' ,
149+ 'Reload'
150+ ) ;
151+ if ( reload === 'Reload' ) {
152+ vscode . commands . executeCommand ( 'workbench.action.reloadWindow' ) ;
153+ }
154+ }
155+ }
156+
38157function getClientOptions ( ) : lsp . LanguageClientOptions {
39158 const initializationOptions = {
40159 'diagnostics.minimumSeverity' : config . getServerDiagnosticsMinimumSeverity ( ) ,
0 commit comments