vscode.dart 6.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
// 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 {
  static const String extensionIdentifier = 'Dart-Code.dart-code';

  VsCode._(this.directory, this.extensionDirectory, { Version version })
      : this.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 Iterable<FileSystemEntity> extensionDirs = fs
        .directory(extensionDirectory)
        .listSync()
        .where((FileSystemEntity d) => d is Directory)
        .where(
            (FileSystemEntity d) => d.basename.startsWith(extensionIdentifier));

    if (extensionDirs.isNotEmpty) {
      final FileSystemEntity extensionDir = extensionDirs.first;

      _isValid = true;
      _extensionVersion = new Version.parse(
          extensionDir.basename.substring('$extensionIdentifier-'.length));
      _validationMessages.add('Dart Code extension version $_extensionVersion');
    }
  }

  final String directory;
  final String extensionDirectory;
  final Version version;

  bool _isValid = false;
  Version _extensionVersion;
  final List<String> _validationMessages = <String>[];

  factory VsCode.fromDirectory(String installPath, String extensionDirectory) {
    final String packageJsonPath =
        fs.path.join(installPath, 'resources', 'app', 'package.json');
    final String versionString = _getVersionFromPackageJson(packageJsonPath);
    Version version;
    if (versionString != null)
      version = new Version.parse(versionString);
    return new VsCode._(installPath, extensionDirectory, version: version);
  }

  bool get isValid => _isValid;

  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() {
    final Map<String, String> stable = <String, String>{
      fs.path.join('/Applications', 'Visual Studio Code.app', 'Contents'):
          '.vscode',
      fs.path.join(homeDirPath, 'Applications', 'Visual Studio Code.app',
          'Contents'): '.vscode'
    };
    final Map<String, String> insiders = <String, String>{
      fs.path.join(
              '/Applications', 'Visual Studio Code - Insiders.app', 'Contents'):
          '.vscode-insiders',
      fs.path.join(homeDirPath, 'Applications',
          'Visual Studio Code - Insiders.app', 'Contents'): '.vscode-insiders'
    };

    return _findInstalled(stable, insiders);
  }

  // Windows:
  //   $programfiles(x86)\Microsoft VS Code
  //   $programfiles(x86)\Microsoft VS Code Insiders
  // TODO: 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 Map<String, String> stable = <String, String>{
      fs.path.join(progFiles86, 'Microsoft VS Code'): '.vscode',
      fs.path.join(progFiles, 'Microsoft VS Code'): '.vscode'
    };
    final Map<String, String> insiders = <String, String>{
      fs.path.join(progFiles86, 'Microsoft VS Code Insiders'):
          '.vscode-insiders',
      fs.path.join(progFiles, 'Microsoft VS Code Insiders'): '.vscode-insiders'
    };

    return _findInstalled(stable, insiders);
  }

  // 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(
      <String, String>{'/usr/share/code': '.vscode'},
      <String, String>{'/usr/share/code-insiders': '.vscode-insiders'}
    );
  }

  static List<VsCode> _findInstalled(
      Map<String, String> stable, Map<String, String> insiders) {
    final Map<String, String> allPaths = <String, String>{};
    allPaths.addAll(stable);
    if (_includeInsiders)
      allPaths.addAll(insiders);

    final List<VsCode> results = <VsCode>[];

    for (String directory in allPaths.keys) {
      if (fs.directory(directory).existsSync()) {
        final String extensionDirectory =
            fs.path.join(homeDirPath, allPaths[directory], 'extensions');
        results.add(new VsCode.fromDirectory(directory, extensionDirectory));
      }
    }

    return results;
  }

  @override
  String toString() =>
      'VS Code ($version)${(_extensionVersion != Version.unknown ? ', Dart Code ($_extensionVersion)' : '')}';

  static String _getVersionFromPackageJson(String packageJsonPath) {
    if (!fs.isFileSync(packageJsonPath))
      return null;
    final String jsonString = fs.file(packageJsonPath).readAsStringSync();
    final Map<String, String> json = JSON.decode(jsonString);
    return json['version'];
  }
}