| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:convert'; |
| |
| import '../base/common.dart'; |
| import '../base/file_system.dart'; |
| import '../base/platform.dart'; |
| import '../base/version.dart'; |
| |
| // Include VS Code insiders (useful for debugging). |
| const bool _includeInsiders = false; |
| |
| class VsCode { |
| VsCode._(this.directory, this.extensionDirectory, { Version version, this.edition }) |
| : version = version ?? Version.unknown { |
| |
| if (!fs.isDirectorySync(directory)) { |
| _validationMessages.add('VS Code not found at $directory'); |
| return; |
| } |
| |
| // If the extensions directory doesn't exist at all, the listSync() |
| // below will fail, so just bail out early. |
| if (!fs.isDirectorySync(extensionDirectory)) { |
| return; |
| } |
| |
| // Check for presence of extension. |
| final String extensionIdentifierLower = extensionIdentifier.toLowerCase(); |
| final Iterable<FileSystemEntity> extensionDirs = fs |
| .directory(extensionDirectory) |
| .listSync() |
| .whereType<Directory>() |
| .where((Directory d) => d.basename.toLowerCase().startsWith(extensionIdentifierLower)); |
| |
| if (extensionDirs.isNotEmpty) { |
| final FileSystemEntity extensionDir = extensionDirs.first; |
| |
| _isValid = true; |
| _extensionVersion = Version.parse( |
| extensionDir.basename.substring('$extensionIdentifier-'.length)); |
| _validationMessages.add('Flutter extension version $_extensionVersion'); |
| } |
| } |
| |
| factory VsCode.fromDirectory(String installPath, String extensionDirectory, |
| { String edition }) { |
| final String packageJsonPath = |
| fs.path.join(installPath, 'resources', 'app', 'package.json'); |
| final String versionString = _getVersionFromPackageJson(packageJsonPath); |
| Version version; |
| if (versionString != null) |
| version = Version.parse(versionString); |
| return VsCode._(installPath, extensionDirectory, version: version, edition: edition); |
| } |
| |
| final String directory; |
| final String extensionDirectory; |
| final Version version; |
| final String edition; |
| |
| static const String extensionIdentifier = 'Dart-Code.flutter'; |
| |
| bool _isValid = false; |
| Version _extensionVersion; |
| final List<String> _validationMessages = <String>[]; |
| |
| bool get isValid => _isValid; |
| String get productName => 'VS Code' + (edition != null ? ', $edition' : ''); |
| |
| Iterable<String> get validationMessages => _validationMessages; |
| |
| static List<VsCode> allInstalled() { |
| if (platform.isMacOS) |
| return _installedMacOS(); |
| else if (platform.isWindows) |
| return _installedWindows(); |
| else if (platform.isLinux) |
| return _installedLinux(); |
| else |
| // VS Code isn't supported on the other platforms. |
| return <VsCode>[]; |
| } |
| |
| // macOS: |
| // /Applications/Visual Studio Code.app/Contents/ |
| // /Applications/Visual Studio Code - Insiders.app/Contents/ |
| // $HOME/Applications/Visual Studio Code.app/Contents/ |
| // $HOME/Applications/Visual Studio Code - Insiders.app/Contents/ |
| // macOS Extensions: |
| // $HOME/.vscode/extensions |
| // $HOME/.vscode-insiders/extensions |
| static List<VsCode> _installedMacOS() { |
| return _findInstalled(<_VsCodeInstallLocation>[ |
| _VsCodeInstallLocation( |
| fs.path.join('/Applications', 'Visual Studio Code.app', 'Contents'), |
| '.vscode', |
| ), |
| _VsCodeInstallLocation( |
| fs.path.join(homeDirPath, 'Applications', 'Visual Studio Code.app', 'Contents'), |
| '.vscode', |
| ), |
| _VsCodeInstallLocation( |
| fs.path.join('/Applications', 'Visual Studio Code - Insiders.app', 'Contents'), |
| '.vscode-insiders', |
| isInsiders: true, |
| ), |
| _VsCodeInstallLocation( |
| fs.path.join(homeDirPath, 'Applications', 'Visual Studio Code - Insiders.app', 'Contents'), |
| '.vscode-insiders', |
| isInsiders: true, |
| ) |
| ]); |
| } |
| |
| // Windows: |
| // $programfiles(x86)\Microsoft VS Code |
| // $programfiles(x86)\Microsoft VS Code Insiders |
| // User install: |
| // $localappdata\Programs\Microsoft VS Code |
| // $localappdata\Programs\Microsoft VS Code Insiders |
| // TODO(dantup): Confirm these are correct for 64bit |
| // $programfiles\Microsoft VS Code |
| // $programfiles\Microsoft VS Code Insiders |
| // Windows Extensions: |
| // $HOME/.vscode/extensions |
| // $HOME/.vscode-insiders/extensions |
| static List<VsCode> _installedWindows() { |
| final String progFiles86 = platform.environment['programfiles(x86)']; |
| final String progFiles = platform.environment['programfiles']; |
| final String localAppData = platform.environment['localappdata']; |
| |
| return _findInstalled(<_VsCodeInstallLocation>[ |
| _VsCodeInstallLocation(fs.path.join(localAppData, 'Programs\\Microsoft VS Code'), '.vscode'), |
| _VsCodeInstallLocation(fs.path.join(progFiles86, 'Microsoft VS Code'), '.vscode', |
| edition: '32-bit edition'), |
| _VsCodeInstallLocation(fs.path.join(progFiles, 'Microsoft VS Code'), '.vscode', |
| edition: '64-bit edition'), |
| _VsCodeInstallLocation(fs.path.join(localAppData, 'Programs\\Microsoft VS Code Insiders'), '.vscode-insiders', |
| isInsiders: true), |
| _VsCodeInstallLocation(fs.path.join(progFiles86 , 'Microsoft VS Code Insiders'), '.vscode-insiders', |
| edition: '32-bit edition', isInsiders: true), |
| _VsCodeInstallLocation(fs.path.join(progFiles, 'Microsoft VS Code Insiders'), '.vscode-insiders', |
| edition: '64-bit edition', isInsiders: true), |
| ]); |
| } |
| |
| // Linux: |
| // /usr/share/code/bin/code |
| // /usr/share/code-insiders/bin/code-insiders |
| // Linux Extensions: |
| // $HOME/.vscode/extensions |
| // $HOME/.vscode-insiders/extensions |
| static List<VsCode> _installedLinux() { |
| return _findInstalled(<_VsCodeInstallLocation>[ |
| const _VsCodeInstallLocation('/usr/share/code', '.vscode'), |
| const _VsCodeInstallLocation('/usr/share/code-insiders', '.vscode-insiders', isInsiders: true), |
| ]); |
| } |
| |
| static List<VsCode> _findInstalled( |
| List<_VsCodeInstallLocation> allLocations) { |
| final Iterable<_VsCodeInstallLocation> searchLocations = |
| _includeInsiders |
| ? allLocations |
| : allLocations.where((_VsCodeInstallLocation p) => p.isInsiders != true); |
| |
| final List<VsCode> results = <VsCode>[]; |
| |
| for (_VsCodeInstallLocation searchLocation in searchLocations) { |
| if (fs.isDirectorySync(searchLocation.installPath)) { |
| final String extensionDirectory = |
| fs.path.join(homeDirPath, searchLocation.extensionsFolder, 'extensions'); |
| results.add(VsCode.fromDirectory(searchLocation.installPath, extensionDirectory, edition: searchLocation.edition)); |
| } |
| } |
| |
| return results; |
| } |
| |
| @override |
| String toString() => |
| 'VS Code ($version)${_extensionVersion != Version.unknown ? ', Flutter ($_extensionVersion)' : ''}'; |
| |
| static String _getVersionFromPackageJson(String packageJsonPath) { |
| if (!fs.isFileSync(packageJsonPath)) |
| return null; |
| final String jsonString = fs.file(packageJsonPath).readAsStringSync(); |
| final Map<String, dynamic> jsonObject = json.decode(jsonString); |
| return jsonObject['version']; |
| } |
| } |
| |
| class _VsCodeInstallLocation { |
| const _VsCodeInstallLocation(this.installPath, this.extensionsFolder, { this.edition, bool isInsiders }) |
| : isInsiders = isInsiders ?? false; |
| final String installPath; |
| final String extensionsFolder; |
| final String edition; |
| final bool isInsiders; |
| } |