11'use strict' ;
22
3- import { ExtensionContext , window , workspace , commands , Uri , ProgressLocation , ViewColumn , EventEmitter , extensions , Location , languages , CodeActionKind , TextEditor , CancellationToken } from "vscode" ;
3+ import { ExtensionContext , window , workspace , commands , Uri , ProgressLocation , ViewColumn , EventEmitter , extensions , Location , languages , CodeActionKind , TextEditor , CancellationToken , ConfigurationTarget , Range , Position } from "vscode" ;
44import { Commands } from "./commands" ;
55import { serverStatus , ServerStatusKind } from "./serverStatus" ;
66import { prepareExecutable , awaitServerConnection } from "./javaServerStarter" ;
77import { getJavaConfig , applyWorkspaceEdit } from "./extension" ;
88import { LanguageClientOptions , Position as LSPosition , Location as LSLocation , MessageType , TextDocumentPositionParams , ConfigurationRequest , ConfigurationParams } from "vscode-languageclient" ;
99import { LanguageClient , StreamInfo } from "vscode-languageclient/node" ;
10- import { CompileWorkspaceRequest , CompileWorkspaceStatus , SourceAttachmentRequest , SourceAttachmentResult , SourceAttachmentAttribute , ProjectConfigurationUpdateRequest , FeatureStatus , StatusNotification , ProgressReportNotification , ActionableNotification , ExecuteClientCommandRequest , ServerNotification , EventNotification , EventType , LinkLocation , FindLinks } from "./protocol" ;
10+ import { CompileWorkspaceRequest , CompileWorkspaceStatus , SourceAttachmentRequest , SourceAttachmentResult , SourceAttachmentAttribute , ProjectConfigurationUpdateRequest , FeatureStatus , StatusNotification , ProgressReportNotification , ActionableNotification , ExecuteClientCommandRequest , ServerNotification , EventNotification , EventType , LinkLocation , FindLinks , GradleCompatibilityInfo } from "./protocol" ;
1111import { setGradleWrapperChecksum , excludeProjectSettingsFiles , ServerMode } from "./settings" ;
1212import { onExtensionChange , collectBuildFilePattern } from "./plugin" ;
1313import { activationProgressNotification , serverTaskPresenter } from "./serverTaskPresenter" ;
14- import { RequirementsData } from "./requirements" ;
14+ import { getJdkUrl , RequirementsData , sortJdksBySource , sortJdksByVersion } from "./requirements" ;
1515import * as net from 'net' ;
1616import * as fse from 'fs-extra' ;
1717import * as path from 'path' ;
@@ -32,9 +32,15 @@ import { typeHierarchyTree } from "./typeHierarchy/typeHierarchyTree";
3232import { TypeHierarchyDirection , TypeHierarchyItem } from "./typeHierarchy/protocol" ;
3333import { buildFilePatterns } from './plugin' ;
3434import { pomCodeActionMetadata , PomCodeActionProvider } from "./pom/pomCodeActionProvider" ;
35+ import { findRuntimes , IJavaRuntime } from "jdk-utils" ;
3536
3637const extensionName = 'Language Support for Java' ;
3738const GRADLE_CHECKSUM = "gradle/checksum/prompt" ;
39+ const GET_JDK = "Get the Java Development Kit" ;
40+ const USE_JAVA = "Use Java " ;
41+ const AS_GRADLE_JVM = " as Gradle JVM" ;
42+ const UPGRADE_GRADLE = "Upgrade Gradle to " ;
43+ const GRADLE_IMPORT_JVM = "java.import.gradle.java.home" ;
3844
3945export class StandardLanguageClient {
4046
@@ -141,7 +147,7 @@ export class StandardLanguageClient {
141147 serverTasks . updateServerTask ( progress ) ;
142148 } ) ;
143149
144- this . languageClient . onNotification ( EventNotification . type , ( notification ) => {
150+ this . languageClient . onNotification ( EventNotification . type , async ( notification ) => {
145151 switch ( notification . eventType ) {
146152 case EventType . ClasspathUpdated :
147153 apiManager . fireDidClasspathUpdate ( Uri . parse ( notification . data ) ) ;
@@ -157,6 +163,23 @@ export class StandardLanguageClient {
157163 apiManager . fireDidProjectsImport ( projectUris ) ;
158164 }
159165 break ;
166+ case EventType . IncompatibleGradleJdkIssue :
167+ const options : string [ ] = [ ] ;
168+ const info = notification . data as GradleCompatibilityInfo ;
169+ const highestJavaVersion = Number ( info . highestJavaVersion ) ;
170+ let runtimes = await findRuntimes ( { checkJavac : true , withVersion : true , withTags : true } ) ;
171+ runtimes = runtimes . filter ( runtime => {
172+ return runtime . version . major <= highestJavaVersion ;
173+ } ) ;
174+ sortJdksByVersion ( runtimes ) ;
175+ sortJdksBySource ( runtimes ) ;
176+ options . push ( UPGRADE_GRADLE + info . recommendedGradleVersion ) ;
177+ if ( ! runtimes . length ) {
178+ options . push ( GET_JDK ) ;
179+ } else {
180+ options . push ( USE_JAVA + runtimes [ 0 ] . version . major + AS_GRADLE_JVM ) ;
181+ }
182+ this . showGradleCompatibilityIssueNotification ( info . message , options , info . projectUri , runtimes [ 0 ] ?. homedir ) ;
160183 default :
161184 break ;
162185 }
@@ -230,6 +253,44 @@ export class StandardLanguageClient {
230253 this . status = ClientStatus . Initialized ;
231254 }
232255
256+ private showGradleCompatibilityIssueNotification ( message : string , options : string [ ] , projectUri : string , newJavaHome : string ) {
257+ window . showErrorMessage ( message + " [Learn More](https://docs.gradle.org/current/userguide/compatibility.html)" , ...options ) . then ( async ( choice ) => {
258+ if ( choice === GET_JDK ) {
259+ commands . executeCommand ( Commands . OPEN_BROWSER , Uri . parse ( getJdkUrl ( ) ) ) ;
260+ } else if ( choice . startsWith ( USE_JAVA ) ) {
261+ await workspace . getConfiguration ( ) . update ( GRADLE_IMPORT_JVM , newJavaHome , ConfigurationTarget . Global ) ;
262+ commands . executeCommand ( "workbench.action.openSettings" , GRADLE_IMPORT_JVM ) ;
263+ commands . executeCommand ( Commands . IMPORT_PROJECTS ) ;
264+ } else if ( choice . startsWith ( UPGRADE_GRADLE ) ) {
265+ const useWrapper = workspace . getConfiguration ( ) . get < boolean > ( "java.import.gradle.wrapper.enabled" ) ;
266+ if ( ! useWrapper ) {
267+ await workspace . getConfiguration ( ) . update ( "java.import.gradle.wrapper.enabled" , true , ConfigurationTarget . Workspace ) ;
268+ }
269+ const result = await window . withProgress ( {
270+ location : ProgressLocation . Notification ,
271+ title : "Upgrading Gradle wrapper..." ,
272+ cancellable : true ,
273+ } , ( _progress , token ) => {
274+ return commands . executeCommand ( Commands . EXECUTE_WORKSPACE_COMMAND , "java.project.upgradeGradle" , projectUri , token ) ;
275+ } ) ;
276+ if ( result ) {
277+ const propertiesFile = path . join ( Uri . parse ( projectUri ) . fsPath , "gradle" , "wrapper" , "gradle-wrapper.properties" ) ;
278+ if ( fse . pathExists ( propertiesFile ) ) {
279+ const content = await fse . readFile ( propertiesFile ) ;
280+ const offset = content . toString ( ) . indexOf ( "distributionUrl" ) ;
281+ if ( offset >= 0 ) {
282+ const document = await workspace . openTextDocument ( propertiesFile ) ;
283+ const position = document . positionAt ( offset ) ;
284+ const distributionUrlRange = document . getWordRangeAtPosition ( position ) ;
285+ window . showTextDocument ( document , { selection : new Range ( distributionUrlRange . start , new Position ( distributionUrlRange . start . line + 1 , 0 ) ) } ) ;
286+ }
287+ }
288+ commands . executeCommand ( Commands . IMPORT_PROJECTS ) ;
289+ }
290+ }
291+ } ) ;
292+ }
293+
233294 private registerCommandsForStandardServer ( context : ExtensionContext , jdtEventEmitter : EventEmitter < Uri > ) : void {
234295 context . subscriptions . push ( commands . registerCommand ( Commands . IMPORT_PROJECTS , async ( ) => {
235296 return await commands . executeCommand < void > ( Commands . EXECUTE_WORKSPACE_COMMAND , Commands . IMPORT_PROJECTS ) ;
0 commit comments