mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

In cases where the VSCode plugins are not located, display links to where they can be downloaded but do not surface an error.
291 lines
9.6 KiB
Dart
291 lines
9.6 KiB
Dart
// Copyright 2014 The Flutter 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 'package:meta/meta.dart';
|
|
|
|
import '../base/file_system.dart';
|
|
import '../base/platform.dart';
|
|
import '../base/utils.dart';
|
|
import '../base/version.dart';
|
|
import '../convert.dart';
|
|
import '../doctor.dart';
|
|
|
|
// Include VS Code insiders (useful for debugging).
|
|
const bool _includeInsiders = false;
|
|
|
|
const String extensionIdentifier = 'Dart-Code.flutter';
|
|
const String extensionMarketplaceUrl =
|
|
'https://marketplace.visualstudio.com/items?itemName=$extensionIdentifier';
|
|
|
|
class VsCode {
|
|
VsCode._(this.directory, this.extensionDirectory, { Version version, this.edition, @required FileSystem fileSystem})
|
|
: version = version ?? Version.unknown {
|
|
|
|
if (!fileSystem.isDirectorySync(directory)) {
|
|
_validationMessages.add(ValidationMessage.error('VS Code not found at $directory'));
|
|
return;
|
|
} else {
|
|
_validationMessages.add(ValidationMessage('VS Code at $directory'));
|
|
}
|
|
|
|
// If the extensions directory doesn't exist at all, the listSync()
|
|
// below will fail, so just bail out early.
|
|
const ValidationMessage notInstalledMessage = ValidationMessage(
|
|
'Flutter extension can be installed from:',
|
|
contextUrl: extensionMarketplaceUrl,
|
|
);
|
|
if (!fileSystem.isDirectorySync(extensionDirectory)) {
|
|
_validationMessages.add(notInstalledMessage);
|
|
return;
|
|
}
|
|
|
|
// Check for presence of extension.
|
|
final String extensionIdentifierLower = extensionIdentifier.toLowerCase();
|
|
final Iterable<FileSystemEntity> extensionDirs = fileSystem
|
|
.directory(extensionDirectory)
|
|
.listSync()
|
|
.whereType<Directory>()
|
|
.where((Directory d) => d.basename.toLowerCase().startsWith(extensionIdentifierLower));
|
|
|
|
if (extensionDirs.isNotEmpty) {
|
|
final FileSystemEntity extensionDir = extensionDirs.first;
|
|
|
|
_extensionVersion = Version.parse(
|
|
extensionDir.basename.substring('$extensionIdentifier-'.length));
|
|
_validationMessages.add(ValidationMessage('Flutter extension version $_extensionVersion'));
|
|
} else {
|
|
_validationMessages.add(notInstalledMessage);
|
|
}
|
|
}
|
|
|
|
factory VsCode.fromDirectory(
|
|
String installPath,
|
|
String extensionDirectory, {
|
|
String edition,
|
|
@required FileSystem fileSystem,
|
|
}) {
|
|
final String packageJsonPath =
|
|
fileSystem.path.join(installPath, 'resources', 'app', 'package.json');
|
|
final String versionString = _getVersionFromPackageJson(packageJsonPath, fileSystem);
|
|
Version version;
|
|
if (versionString != null) {
|
|
version = Version.parse(versionString);
|
|
}
|
|
return VsCode._(installPath, extensionDirectory, version: version, edition: edition, fileSystem: fileSystem);
|
|
}
|
|
|
|
final String directory;
|
|
final String extensionDirectory;
|
|
final Version version;
|
|
final String edition;
|
|
|
|
Version _extensionVersion;
|
|
final List<ValidationMessage> _validationMessages = <ValidationMessage>[];
|
|
|
|
String get productName => 'VS Code' + (edition != null ? ', $edition' : '');
|
|
|
|
Iterable<ValidationMessage> get validationMessages => _validationMessages;
|
|
|
|
static List<VsCode> allInstalled(
|
|
FileSystem fileSystem,
|
|
Platform platform,
|
|
) {
|
|
if (platform.isMacOS) {
|
|
return _installedMacOS(fileSystem, platform);
|
|
}
|
|
if (platform.isWindows) {
|
|
return _installedWindows(fileSystem, platform);
|
|
}
|
|
if (platform.isLinux) {
|
|
return _installedLinux(fileSystem, platform);
|
|
}
|
|
// 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(FileSystem fileSystem, Platform platform) {
|
|
return _findInstalled(<_VsCodeInstallLocation>[
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join('/Applications', 'Visual Studio Code.app', 'Contents'),
|
|
'.vscode',
|
|
),
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(
|
|
FileSystemUtils(fileSystem: fileSystem, platform: platform).homeDirPath,
|
|
'Applications',
|
|
'Visual Studio Code.app',
|
|
'Contents',
|
|
),
|
|
'.vscode',
|
|
),
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join('/Applications', 'Visual Studio Code - Insiders.app', 'Contents'),
|
|
'.vscode-insiders',
|
|
isInsiders: true,
|
|
),
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(
|
|
FileSystemUtils(fileSystem: fileSystem, platform: platform).homeDirPath,
|
|
'Applications',
|
|
'Visual Studio Code - Insiders.app',
|
|
'Contents',
|
|
),
|
|
'.vscode-insiders',
|
|
isInsiders: true,
|
|
),
|
|
], fileSystem, platform);
|
|
}
|
|
|
|
// 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(
|
|
FileSystem fileSystem,
|
|
Platform platform,
|
|
) {
|
|
final String progFiles86 = platform.environment['programfiles(x86)'];
|
|
final String progFiles = platform.environment['programfiles'];
|
|
final String localAppData = platform.environment['localappdata'];
|
|
|
|
final List<_VsCodeInstallLocation> searchLocations = <_VsCodeInstallLocation>[
|
|
if (localAppData != null)
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(localAppData, r'Programs\Microsoft VS Code'),
|
|
'.vscode',
|
|
),
|
|
if (progFiles86 != null)
|
|
...<_VsCodeInstallLocation>[
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(progFiles86, 'Microsoft VS Code'),
|
|
'.vscode',
|
|
edition: '32-bit edition',
|
|
),
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(progFiles86, 'Microsoft VS Code Insiders'),
|
|
'.vscode-insiders',
|
|
edition: '32-bit edition',
|
|
isInsiders: true,
|
|
),
|
|
],
|
|
if (progFiles != null)
|
|
...<_VsCodeInstallLocation>[
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(progFiles, 'Microsoft VS Code'),
|
|
'.vscode',
|
|
edition: '64-bit edition',
|
|
),
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(progFiles, 'Microsoft VS Code Insiders'),
|
|
'.vscode-insiders',
|
|
edition: '64-bit edition',
|
|
isInsiders: true,
|
|
),
|
|
],
|
|
if (localAppData != null)
|
|
_VsCodeInstallLocation(
|
|
fileSystem.path.join(localAppData, r'Programs\Microsoft VS Code Insiders'),
|
|
'.vscode-insiders',
|
|
isInsiders: true,
|
|
),
|
|
];
|
|
return _findInstalled(searchLocations, fileSystem, platform);
|
|
}
|
|
|
|
// 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(FileSystem fileSystem, Platform platform) {
|
|
return _findInstalled(<_VsCodeInstallLocation>[
|
|
const _VsCodeInstallLocation('/usr/share/code', '.vscode'),
|
|
const _VsCodeInstallLocation(
|
|
'/usr/share/code-insiders',
|
|
'.vscode-insiders',
|
|
isInsiders: true,
|
|
),
|
|
], fileSystem, platform);
|
|
}
|
|
|
|
static List<VsCode> _findInstalled(
|
|
List<_VsCodeInstallLocation> allLocations,
|
|
FileSystem fileSystem,
|
|
Platform platform,
|
|
) {
|
|
final Iterable<_VsCodeInstallLocation> searchLocations =
|
|
_includeInsiders
|
|
? allLocations
|
|
: allLocations.where((_VsCodeInstallLocation p) => p.isInsiders != true);
|
|
|
|
final List<VsCode> results = <VsCode>[];
|
|
|
|
for (final _VsCodeInstallLocation searchLocation in searchLocations) {
|
|
if (fileSystem.isDirectorySync(searchLocation.installPath)) {
|
|
final String extensionDirectory = fileSystem.path.join(
|
|
FileSystemUtils(fileSystem: fileSystem, platform: platform).homeDirPath,
|
|
searchLocation.extensionsFolder,
|
|
'extensions',
|
|
);
|
|
results.add(VsCode.fromDirectory(
|
|
searchLocation.installPath,
|
|
extensionDirectory,
|
|
edition: searchLocation.edition,
|
|
fileSystem: fileSystem,
|
|
));
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
@override
|
|
String toString() =>
|
|
'VS Code ($version)${_extensionVersion != Version.unknown ? ', Flutter ($_extensionVersion)' : ''}';
|
|
|
|
static String _getVersionFromPackageJson(String packageJsonPath, FileSystem fileSystem) {
|
|
if (!fileSystem.isFileSync(packageJsonPath)) {
|
|
return null;
|
|
}
|
|
final String jsonString = fileSystem.file(packageJsonPath).readAsStringSync();
|
|
try {
|
|
final Map<String, dynamic> jsonObject = castStringKeyedMap(json.decode(jsonString));
|
|
return jsonObject['version'] as String;
|
|
} on FormatException {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|