55'use strict' ;
66
77import * as vscode from 'vscode' ;
8- import * as child_process from 'child_process' ;
98import * as fs from 'fs' ;
10- import * as path from 'path' ;
119import TelemetryReporter from 'vscode-extension-telemetry' ;
1210import { CoreClrDebugUtil } from './util' ;
1311import * as debugInstall from './install' ;
1412import { Platform , getCurrentPlatform } from './../platform' ;
13+ import * as semver from 'semver' ;
14+
15+ const MINIMUM_SUPPORTED_DOTNET_CLI : string = '1.0.0-preview2-003121' ;
1516
1617let _reporter : TelemetryReporter = null ;
1718let _channel : vscode . OutputChannel = null ;
1819let _util : CoreClrDebugUtil = null ;
1920
21+ class DotnetInfo
22+ {
23+ public Version : string ;
24+ public OsVersion : string ;
25+ public RuntimeId : string ;
26+ }
27+
2028export function activate ( context : vscode . ExtensionContext , reporter : TelemetryReporter ) {
2129 _reporter = reporter ;
2230 _channel = vscode . window . createOutputChannel ( 'coreclr-debug' ) ;
@@ -27,22 +35,7 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe
2735 return ;
2836 }
2937
30- let dotnetVersion : string = '' ;
31- let osVersion : string = '' ;
32- let osRID : string = '' ;
33- _util . spawnChildProcess ( 'dotnet' , [ '--info' ] , _util . coreClrDebugDir ( ) , ( data : Buffer ) => {
34- var lines : string [ ] = data . toString ( ) . replace ( / \r / mg, '' ) . split ( '\n' ) ;
35- lines . forEach ( line => {
36- let match : RegExpMatchArray ;
37- if ( match = / ^ \ V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
38- dotnetVersion = match [ 1 ] ;
39- } else if ( match = / ^ \ O S V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
40- osVersion = match [ 1 ] ;
41- } else if ( match = / ^ \ R I D : \s * ( [ \w \- \. ] + ) $ / . exec ( line ) ) {
42- osRID = match [ 1 ] ;
43- }
44- } ) ;
45- } ) . then ( ( ) => {
38+ checkForDotnetTools ( ) . then ( ( dotnetInfo : DotnetInfo ) => {
4639 let installer = new debugInstall . DebugInstaller ( _util ) ;
4740 _util . createInstallLog ( ) ;
4841
@@ -61,54 +54,98 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe
6154 statusBarMessage . dispose ( ) ;
6255 vscode . window . setStatusBarMessage ( 'Successfully installed .NET Core Debugger.' ) ;
6356 } ) . catch ( ( error : debugInstall . InstallError ) => {
64- const viewLogMessage = "View Log" ;
65- vscode . window . showErrorMessage ( 'Error while installing .NET Core Debugger.' , viewLogMessage ) . then ( value => {
66- if ( value === viewLogMessage ) {
67- _channel . show ( vscode . ViewColumn . Three ) ;
68- }
69- } ) ;
70- statusBarMessage . dispose ( ) ;
71-
72- installStage = error . installStage ;
73- installError = error . errorMessage ;
74- moreErrors = error . hasMoreErrors ? 'true' : 'false' ;
75- } ) . then ( ( ) => {
76- // log telemetry and delete install begin file
77- logTelemetry ( 'Acquisition' , {
78- installStage : installStage ,
79- installError : installError ,
80- moreErrors : moreErrors ,
81- dotnetVersion : dotnetVersion ,
82- osVersion : osVersion ,
83- osRID : osRID
84- } ) ;
85- try {
86- deleteInstallBeginFile ( ) ;
87- } catch ( err ) {
88- // if this throws there's really nothing we can do
57+ const viewLogMessage = "View Log" ;
58+ vscode . window . showErrorMessage ( 'Error while installing .NET Core Debugger.' , viewLogMessage ) . then ( value => {
59+ if ( value === viewLogMessage ) {
60+ _channel . show ( vscode . ViewColumn . Three ) ;
8961 }
90- _util . closeInstallLog ( ) ;
9162 } ) ;
92- } ) . catch ( ( ) => {
93- const config = vscode . workspace . getConfiguration ( 'csharp' ) ;
94- if ( ! config . get ( 'suppressDotnetInstallWarning' , false ) ) {
95- const getDotNetMessage = 'Get .NET CLI tools' ;
96- const goToSettingsMessage = 'Disable this message in user settings' ;
97- // Buttons are shown in right-to-left order, with a close button to the right of everything;
98- // getDotNetMessage will be the first button, then goToSettingsMessage, then the close button.
99- vscode . window . showErrorMessage ( 'The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.' ,
100- goToSettingsMessage , getDotNetMessage ) . then ( value => {
101- if ( value === getDotNetMessage ) {
102- let open = require ( 'open' ) ;
103- open ( 'https://www.microsoft.com/net/core' ) ;
104- } else if ( value === goToSettingsMessage ) {
105- vscode . commands . executeCommand ( 'workbench.action.openGlobalSettings' ) ;
106- }
107- } ) ;
63+ statusBarMessage . dispose ( ) ;
64+
65+ installStage = error . installStage ;
66+ installError = error . errorMessage ;
67+ moreErrors = error . hasMoreErrors ? 'true' : 'false' ;
68+ } ) . then ( ( ) => {
69+ // log telemetry and delete install begin file
70+ logTelemetry ( 'Acquisition' , {
71+ installStage : installStage ,
72+ installError : installError ,
73+ moreErrors : moreErrors ,
74+ dotnetVersion : dotnetInfo . Version ,
75+ osVersion : dotnetInfo . OsVersion ,
76+ osRID : dotnetInfo . RuntimeId
77+ } ) ;
78+ try {
79+ deleteInstallBeginFile ( ) ;
80+ } catch ( err ) {
81+ // if this throws there's really nothing we can do
82+ }
83+ _util . closeInstallLog ( ) ;
84+ } ) ;
85+ } ) . catch ( ( error ) => {
86+ // log errors from checkForDotnetTools
87+ _util . log ( error . message ) ;
88+ } ) ;
89+ }
90+
91+ // This function checks for the presence of dotnet on the path and ensures the Version
92+ // is new enough for us. Any error UI that needs to be displayed is handled by this function.
93+ // Returns: a promise that returns a DotnetInfo class
94+ // Throws: An Error() from the return promise if either dotnet does not exist or is too old.
95+ function checkForDotnetTools ( ) : Promise < DotnetInfo >
96+ {
97+ let dotnetInfo = new DotnetInfo ( ) ;
98+
99+ return _util . spawnChildProcess ( 'dotnet' , [ '--info' ] , _util . coreClrDebugDir ( ) , ( data : Buffer ) => {
100+ let lines : string [ ] = data . toString ( ) . replace ( / \r / mg, '' ) . split ( '\n' ) ;
101+ lines . forEach ( line => {
102+ let match : RegExpMatchArray ;
103+ if ( match = / ^ \ V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
104+ dotnetInfo . Version = match [ 1 ] ;
105+ } else if ( match = / ^ \ O S V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
106+ dotnetInfo . OsVersion = match [ 1 ] ;
107+ } else if ( match = / ^ \ R I D : \s * ( [ \w \- \. ] + ) $ / . exec ( line ) ) {
108+ dotnetInfo . RuntimeId = match [ 1 ] ;
109+ }
110+ } ) ;
111+ } ) . catch ( ( error ) => {
112+ // something went wrong with spawning 'dotnet --info'
113+ let message = 'The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.' ;
114+ showDotnetToolsWarning ( message ) ;
115+ throw new Error ( "Failed to spawn 'dotnet --info'" ) ;
116+ } ) . then ( ( ) => {
117+ // succesfully spawned 'dotnet --info', check the Version
118+ if ( semver . lt ( dotnetInfo . Version , MINIMUM_SUPPORTED_DOTNET_CLI ) )
119+ {
120+ let message = 'The .NET CLI tools on the path are too old. .NET Core debugging will not be enabled. The minimum supported version is ' + MINIMUM_SUPPORTED_DOTNET_CLI + '.' ;
121+ showDotnetToolsWarning ( message ) ;
122+ throw new Error ( "dotnet cli is too old" ) ;
108123 }
124+
125+ return dotnetInfo ;
109126 } ) ;
110127}
111128
129+ function showDotnetToolsWarning ( message : string ) : void
130+ {
131+ const config = vscode . workspace . getConfiguration ( 'csharp' ) ;
132+ if ( ! config . get ( 'suppressDotnetInstallWarning' , false ) ) {
133+ const getDotNetMessage = 'Get .NET CLI tools' ;
134+ const goToSettingsMessage = 'Disable this message in user settings' ;
135+ // Buttons are shown in right-to-left order, with a close button to the right of everything;
136+ // getDotNetMessage will be the first button, then goToSettingsMessage, then the close button.
137+ vscode . window . showErrorMessage ( message ,
138+ goToSettingsMessage , getDotNetMessage ) . then ( value => {
139+ if ( value === getDotNetMessage ) {
140+ let open = require ( 'open' ) ;
141+ open ( 'https://www.microsoft.com/net/core' ) ;
142+ } else if ( value === goToSettingsMessage ) {
143+ vscode . commands . executeCommand ( 'workbench.action.openGlobalSettings' ) ;
144+ }
145+ } ) ;
146+ }
147+ }
148+
112149function logTelemetry ( eventName : string , properties ?: { [ prop : string ] : string } ) : void {
113150 if ( _reporter !== null ) {
114151 _reporter . sendTelemetryEvent ( 'coreclr-debug/' + eventName , properties ) ;
0 commit comments