1+ /*---------------------------------------------------------------------------------------------
2+ * Copyright (c) Microsoft Corporation. All rights reserved.
3+ * Licensed under the MIT License. See License.txt in the project root for license information.
4+ *--------------------------------------------------------------------------------------------*/
5+
6+ import * as vscode from "vscode" ;
7+ import * as semver from "semver" ;
8+ import { getDotnetInfo } from "../utils/getDotnetInfo" ;
9+ import { Options } from "./options" ;
10+ import { getMonoVersion } from "../utils/getMonoVersion" ;
11+ import { OmniSharpMonoResolver } from "./OmniSharpMonoResolver" ;
12+ import { getMSBuildVersion } from "../utils/getMSBuildInfo" ;
13+
14+ export interface RequirementResult {
15+ needsDotNetSdk : boolean ;
16+ needsMono : boolean ;
17+ needsMSBuildTools : boolean ;
18+ }
19+
20+ export async function validateRequirements ( options : Options ) : Promise < boolean > {
21+ const result = await checkRequirements ( options ) ;
22+
23+ if ( result . needsDotNetSdk ) {
24+ const downloadSdk = await promptToDownloadDotNetSDK ( ) ;
25+
26+ if ( downloadSdk === PromptResult . Yes ) {
27+ let dotnetcoreURL = 'https://dot.net/core-sdk-vscode' ;
28+ vscode . env . openExternal ( vscode . Uri . parse ( dotnetcoreURL ) ) ;
29+ } else if ( downloadSdk === PromptResult . No ) {
30+ vscode . commands . executeCommand ( 'workbench.action.openGlobalSettings' ) ;
31+ }
32+
33+ return false ;
34+ }
35+
36+ if ( result . needsMono
37+ || result . needsMSBuildTools ) { // Since we are currently not checking for MSBuild Tools on Windows this indicates a partial install of Mono.
38+
39+ const downloadMono = await promptToDownloadMono ( ) ;
40+
41+ if ( downloadMono === PromptResult . Yes ) {
42+ let monoURL = 'https://www.mono-project.com/download/stable/' ;
43+ vscode . env . openExternal ( vscode . Uri . parse ( monoURL ) ) ;
44+ } else if ( downloadMono === PromptResult . No ) {
45+ vscode . commands . executeCommand ( 'workbench.action.openGlobalSettings' ) ;
46+ }
47+
48+ return false ;
49+ }
50+
51+ return true ;
52+ }
53+
54+ async function checkRequirements ( options : Options ) : Promise < RequirementResult > {
55+ if ( options . useModernNet ) {
56+ const dotnetInfo = await getDotnetInfo ( options . dotNetCliPaths ) ;
57+ const needsDotNetSdk = dotnetInfo . Version === undefined || semver . lt ( dotnetInfo . Version , '6.0.0' ) ;
58+ return {
59+ needsDotNetSdk,
60+ needsMono : false ,
61+ needsMSBuildTools : false ,
62+ } ;
63+ }
64+
65+ if ( process . platform === 'win32' ) {
66+ // Need to determine way to surface missing MSBuild Tools for windows.
67+ return {
68+ needsMSBuildTools : false ,
69+ needsDotNetSdk : false ,
70+ needsMono : false ,
71+ } ;
72+ }
73+ else {
74+ const monoResolver = new OmniSharpMonoResolver ( getMonoVersion ) ;
75+ let monoError : Error | undefined ;
76+ try {
77+ await monoResolver . getHostExecutableInfo ( options ) ;
78+ } catch ( e ) {
79+ monoError = e ;
80+ }
81+
82+ const msbuildVersion = await getMSBuildVersion ( ) ;
83+
84+ return {
85+ needsMono : monoError !== undefined ,
86+ needsDotNetSdk : false ,
87+ needsMSBuildTools : msbuildVersion !== undefined ,
88+ } ;
89+ }
90+ }
91+
92+ enum PromptResult {
93+ Dismissed ,
94+ Yes ,
95+ No
96+ }
97+
98+ interface PromptItem extends vscode . MessageItem {
99+ result : PromptResult ;
100+ }
101+
102+ async function promptToDownloadDotNetSDK ( ) {
103+ return new Promise < PromptResult > ( ( resolve , reject ) => {
104+ const message = 'OmniSharp requires an install of the .NET SDK to provide language services when `omnisharp.useModernNet` is enabled in Settings. Please install the latest .NET SDK and restart.' ;
105+
106+ const messageOptions : vscode . MessageOptions = { modal : true } ;
107+
108+ const yesItem : PromptItem = { title : 'Get the SDK' , result : PromptResult . Yes } ;
109+ const noItem : PromptItem = { title : 'Open settings' , result : PromptResult . No , isCloseAffordance : true } ;
110+
111+ vscode . window . showErrorMessage ( message , messageOptions , noItem , yesItem )
112+ . then ( selection => resolve ( selection ?. result ?? PromptResult . Dismissed ) ) ;
113+ } ) ;
114+ }
115+
116+ async function promptToDownloadMono ( ) {
117+ return new Promise < PromptResult > ( ( resolve , reject ) => {
118+ const message = 'OmniSharp requires a complete install of Mono (including MSBuild) to provide language services when `omnisharp.useModernNet` is disabled in Settings. Please install the latest Mono and restart.' ;
119+
120+ const messageOptions : vscode . MessageOptions = { modal : true } ;
121+
122+ const yesItem : PromptItem = { title : 'Download Mono' , result : PromptResult . Yes } ;
123+ const noItem : PromptItem = { title : 'Open settings' , result : PromptResult . No , isCloseAffordance : true } ;
124+
125+ vscode . window . showErrorMessage ( message , messageOptions , noItem , yesItem )
126+ . then ( selection => resolve ( selection ?. result ?? PromptResult . Dismissed ) ) ;
127+ } ) ;
128+ }
0 commit comments