Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
7aa188ba
Unverified
Commit
7aa188ba
authored
Apr 17, 2021
by
Jenn Magder
Committed by
GitHub
Apr 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Find VS Code installations with Spotlight query on macOS (#80477)
parent
8d5f08fe
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
154 additions
and
30 deletions
+154
-30
doctor.dart
packages/flutter_tools/lib/src/doctor.dart
+1
-1
vscode.dart
packages/flutter_tools/lib/src/vscode/vscode.dart
+77
-26
vscode_validator.dart
packages/flutter_tools/lib/src/vscode/vscode_validator.dart
+4
-2
vscode_test.dart
.../flutter_tools/test/general.shard/vscode/vscode_test.dart
+70
-0
vscode_validator_test.dart
...ools/test/general.shard/vscode/vscode_validator_test.dart
+2
-1
No files found.
packages/flutter_tools/lib/src/doctor.dart
View file @
7aa188ba
...
...
@@ -86,7 +86,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
plistParser:
globals
.
plistParser
,
processManager:
globals
.
processManager
,
),
...
VsCodeValidator
.
installedValidators
(
globals
.
fs
,
globals
.
platform
),
...
VsCodeValidator
.
installedValidators
(
globals
.
fs
,
globals
.
platform
,
globals
.
processManager
),
];
final
ProxyValidator
proxyValidator
=
ProxyValidator
(
platform:
globals
.
platform
);
_validators
=
<
DoctorValidator
>[
...
...
packages/flutter_tools/lib/src/vscode/vscode.dart
View file @
7aa188ba
...
...
@@ -2,7 +2,11 @@
// 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
'package:process/process.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/platform.dart'
;
import
'../base/utils.dart'
;
import
'../base/version.dart'
;
...
...
@@ -88,9 +92,10 @@ class VsCode {
static
List
<
VsCode
>
allInstalled
(
FileSystem
fileSystem
,
Platform
platform
,
ProcessManager
processManager
,
)
{
if
(
platform
.
isMacOS
)
{
return
_installedMacOS
(
fileSystem
,
platform
);
return
_installedMacOS
(
fileSystem
,
platform
,
processManager
);
}
if
(
platform
.
isWindows
)
{
return
_installedWindows
(
fileSystem
,
platform
);
...
...
@@ -110,15 +115,35 @@ class VsCode {
// macOS Extensions:
// $HOME/.vscode/extensions
// $HOME/.vscode-insiders/extensions
static
List
<
VsCode
>
_installedMacOS
(
FileSystem
fileSystem
,
Platform
platform
)
{
static
List
<
VsCode
>
_installedMacOS
(
FileSystem
fileSystem
,
Platform
platform
,
ProcessManager
processManager
)
{
final
String
?
homeDirPath
=
FileSystemUtils
(
fileSystem:
fileSystem
,
platform:
platform
).
homeDirPath
;
return
_findInstalled
(<
_VsCodeInstallLocation
>[
_VsCodeInstallLocation
(
String
vsCodeSpotlightResult
=
''
;
String
vsCodeInsiderSpotlightResult
=
''
;
// Query Spotlight for unexpected installation locations.
try
{
final
ProcessResult
vsCodeSpotlightQueryResult
=
processManager
.
runSync
(<
String
>[
'mdfind'
,
'kMDItemCFBundleIdentifier="com.microsoft.VSCode"'
,
]);
vsCodeSpotlightResult
=
vsCodeSpotlightQueryResult
.
stdout
as
String
;
final
ProcessResult
vsCodeInsidersSpotlightQueryResult
=
processManager
.
runSync
(<
String
>[
'mdfind'
,
'kMDItemCFBundleIdentifier="com.microsoft.VSCodeInsiders"'
,
]);
vsCodeInsiderSpotlightResult
=
vsCodeInsidersSpotlightQueryResult
.
stdout
as
String
;
}
on
ProcessException
{
// The Spotlight query is a nice-to-have, continue checking known installation locations.
}
// De-duplicated set.
return
_findInstalled
(<
VsCodeInstallLocation
>{
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
'/Applications'
,
'Visual Studio Code.app'
,
'Contents'
),
'.vscode'
,
),
if
(
homeDirPath
!=
null
)
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
homeDirPath
,
'Applications'
,
...
...
@@ -127,13 +152,13 @@ class VsCode {
),
'.vscode'
,
),
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
'/Applications'
,
'Visual Studio Code - Insiders.app'
,
'Contents'
),
'.vscode-insiders'
,
isInsiders:
true
,
),
if
(
homeDirPath
!=
null
)
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
homeDirPath
,
'Applications'
,
...
...
@@ -143,7 +168,18 @@ class VsCode {
'.vscode-insiders'
,
isInsiders:
true
,
),
],
fileSystem
,
platform
);
for
(
final
String
vsCodePath
in
LineSplitter
.
split
(
vsCodeSpotlightResult
))
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
vsCodePath
,
'Contents'
),
'.vscode'
,
),
for
(
final
String
vsCodeInsidersPath
in
LineSplitter
.
split
(
vsCodeInsiderSpotlightResult
))
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
vsCodeInsidersPath
,
'Contents'
),
'.vscode-insiders'
,
isInsiders:
true
,
),
},
fileSystem
,
platform
);
}
// Windows:
...
...
@@ -166,20 +202,20 @@ class VsCode {
final
String
?
progFiles
=
platform
.
environment
[
'programfiles'
];
final
String
?
localAppData
=
platform
.
environment
[
'localappdata'
];
final
List
<
_VsCodeInstallLocation
>
searchLocations
=
<
_
VsCodeInstallLocation
>[
final
List
<
VsCodeInstallLocation
>
searchLocations
=
<
VsCodeInstallLocation
>[
if
(
localAppData
!=
null
)
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
localAppData
,
r'Programs\Microsoft VS Code'
),
'.vscode'
,
),
if
(
progFiles86
!=
null
)
...<
_
VsCodeInstallLocation
>[
_
VsCodeInstallLocation
(
...<
VsCodeInstallLocation
>[
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
progFiles86
,
'Microsoft VS Code'
),
'.vscode'
,
edition:
'32-bit edition'
,
),
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
progFiles86
,
'Microsoft VS Code Insiders'
),
'.vscode-insiders'
,
edition:
'32-bit edition'
,
...
...
@@ -187,13 +223,13 @@ class VsCode {
),
],
if
(
progFiles
!=
null
)
...<
_
VsCodeInstallLocation
>[
_
VsCodeInstallLocation
(
...<
VsCodeInstallLocation
>[
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
progFiles
,
'Microsoft VS Code'
),
'.vscode'
,
edition:
'64-bit edition'
,
),
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
progFiles
,
'Microsoft VS Code Insiders'
),
'.vscode-insiders'
,
edition:
'64-bit edition'
,
...
...
@@ -201,7 +237,7 @@ class VsCode {
),
],
if
(
localAppData
!=
null
)
_
VsCodeInstallLocation
(
VsCodeInstallLocation
(
fileSystem
.
path
.
join
(
localAppData
,
r'Programs\Microsoft VS Code Insiders'
),
'.vscode-insiders'
,
isInsiders:
true
,
...
...
@@ -217,9 +253,9 @@ class VsCode {
// $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
(
return
_findInstalled
(<
VsCodeInstallLocation
>[
const
VsCodeInstallLocation
(
'/usr/share/code'
,
'.vscode'
),
const
VsCodeInstallLocation
(
'/usr/share/code-insiders'
,
'.vscode-insiders'
,
isInsiders:
true
,
...
...
@@ -228,18 +264,18 @@ class VsCode {
}
static
List
<
VsCode
>
_findInstalled
(
List
<
_
VsCodeInstallLocation
>
allLocations
,
Iterable
<
VsCodeInstallLocation
>
allLocations
,
FileSystem
fileSystem
,
Platform
platform
,
)
{
final
Iterable
<
_
VsCodeInstallLocation
>
searchLocations
=
final
Iterable
<
VsCodeInstallLocation
>
searchLocations
=
_includeInsiders
?
allLocations
:
allLocations
.
where
((
_
VsCodeInstallLocation
p
)
=>
p
.
isInsiders
!=
true
);
:
allLocations
.
where
((
VsCodeInstallLocation
p
)
=>
p
.
isInsiders
!=
true
);
final
List
<
VsCode
>
results
=
<
VsCode
>[];
for
(
final
_
VsCodeInstallLocation
searchLocation
in
searchLocations
)
{
for
(
final
VsCodeInstallLocation
searchLocation
in
searchLocations
)
{
final
String
?
homeDirPath
=
FileSystemUtils
(
fileSystem:
fileSystem
,
platform:
platform
).
homeDirPath
;
if
(
homeDirPath
!=
null
&&
fileSystem
.
isDirectorySync
(
searchLocation
.
installPath
))
{
final
String
extensionDirectory
=
fileSystem
.
path
.
join
(
...
...
@@ -280,8 +316,10 @@ class VsCode {
}
}
class
_VsCodeInstallLocation
{
const
_VsCodeInstallLocation
(
@immutable
@visibleForTesting
class
VsCodeInstallLocation
{
const
VsCodeInstallLocation
(
this
.
installPath
,
this
.
extensionsFolder
,
{
this
.
edition
,
...
...
@@ -292,4 +330,17 @@ class _VsCodeInstallLocation {
final
String
extensionsFolder
;
final
String
?
edition
;
final
bool
isInsiders
;
@override
bool
operator
==(
Object
other
)
{
return
other
is
VsCodeInstallLocation
&&
other
.
installPath
==
installPath
&&
other
.
extensionsFolder
==
extensionsFolder
&&
other
.
edition
==
edition
&&
other
.
isInsiders
==
isInsiders
;
}
@override
// Lowest bit is for isInsiders boolean.
int
get
hashCode
=>
(
installPath
.
hashCode
^
extensionsFolder
.
hashCode
^
edition
.
hashCode
)
<<
1
|
(
isInsiders
?
1
:
0
);
}
packages/flutter_tools/lib/src/vscode/vscode_validator.dart
View file @
7aa188ba
...
...
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:process/process.dart'
;
import
'../base/file_system.dart'
;
import
'../base/platform.dart'
;
import
'../base/user_messages.dart'
;
...
...
@@ -14,9 +16,9 @@ class VsCodeValidator extends DoctorValidator {
final
VsCode
_vsCode
;
static
Iterable
<
DoctorValidator
>
installedValidators
(
FileSystem
fileSystem
,
Platform
platform
)
{
static
Iterable
<
DoctorValidator
>
installedValidators
(
FileSystem
fileSystem
,
Platform
platform
,
ProcessManager
processManager
)
{
return
VsCode
.
allInstalled
(
fileSystem
,
platform
)
.
allInstalled
(
fileSystem
,
platform
,
processManager
)
.
map
<
DoctorValidator
>((
VsCode
vsCode
)
=>
VsCodeValidator
(
vsCode
));
}
...
...
packages/flutter_tools/test/general.shard/vscode/vscode_test.dart
View file @
7aa188ba
...
...
@@ -3,12 +3,35 @@
// found in the LICENSE file.
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:flutter_tools/src/base/version.dart'
;
import
'package:flutter_tools/src/vscode/vscode.dart'
;
import
'../../src/common.dart'
;
import
'../../src/fake_process_manager.dart'
;
void
main
(
)
{
testWithoutContext
(
'VsCodeInstallLocation equality'
,
()
{
const
VsCodeInstallLocation
installLocation1
=
VsCodeInstallLocation
(
'abc'
,
'zyx'
,
edition:
'123'
,
isInsiders:
true
);
const
VsCodeInstallLocation
installLocation2
=
VsCodeInstallLocation
(
'abc'
,
'zyx'
,
edition:
'123'
,
isInsiders:
true
);
const
VsCodeInstallLocation
installLocation3
=
VsCodeInstallLocation
(
'cba'
,
'zyx'
,
edition:
'123'
,
isInsiders:
true
);
const
VsCodeInstallLocation
installLocation4
=
VsCodeInstallLocation
(
'abc'
,
'xyz'
,
edition:
'123'
,
isInsiders:
true
);
const
VsCodeInstallLocation
installLocation5
=
VsCodeInstallLocation
(
'abc'
,
'xyz'
,
edition:
'321'
,
isInsiders:
true
);
const
VsCodeInstallLocation
installLocation6
=
VsCodeInstallLocation
(
'abc'
,
'zyx'
,
edition:
'123'
,
isInsiders:
false
);
expect
(
installLocation1
,
installLocation2
);
expect
(
installLocation1
.
hashCode
,
installLocation2
.
hashCode
);
expect
(
installLocation1
,
isNot
(
installLocation3
));
expect
(
installLocation1
.
hashCode
,
isNot
(
installLocation3
.
hashCode
));
expect
(
installLocation1
,
isNot
(
installLocation4
));
expect
(
installLocation1
.
hashCode
,
isNot
(
installLocation4
.
hashCode
));
expect
(
installLocation1
,
isNot
(
installLocation5
));
expect
(
installLocation1
.
hashCode
,
isNot
(
installLocation5
.
hashCode
));
expect
(
installLocation1
,
isNot
(
installLocation6
));
expect
(
installLocation1
.
hashCode
,
isNot
(
installLocation6
.
hashCode
));
});
testWithoutContext
(
'VsCode.fromDirectory does not crash when packages.json is malformed'
,
()
{
final
MemoryFileSystem
fileSystem
=
MemoryFileSystem
.
test
();
// Create invalid JSON file.
...
...
@@ -20,4 +43,51 @@ void main() {
expect
(
vsCode
.
version
,
Version
.
unknown
);
});
testWithoutContext
(
'can locate non-Insider installations on macOS'
,
()
{
final
FileSystem
fileSystem
=
MemoryFileSystem
.
test
();
const
String
home
=
'/home/me'
;
final
Platform
platform
=
FakePlatform
(
operatingSystem:
'macos'
,
environment:
<
String
,
String
>{
'HOME'
:
home
});
final
String
randomLocation
=
fileSystem
.
path
.
join
(
'/'
,
'random'
,
'Visual Studio Code.app'
,
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
randomLocation
,
'Contents'
)).
createSync
(
recursive:
true
);
final
String
randomInsidersLocation
=
fileSystem
.
path
.
join
(
'/'
,
'random'
,
'Visual Studio Code - Insiders.app'
,
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
randomInsidersLocation
,
'Contents'
)).
createSync
(
recursive:
true
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
'/'
,
'Applications'
,
'Visual Studio Code.app'
,
'Contents'
)).
createSync
(
recursive:
true
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
'/'
,
'Applications'
,
'Visual Studio Code - Insiders.app'
,
'Contents'
)).
createSync
(
recursive:
true
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
home
,
'Applications'
,
'Visual Studio Code.app'
,
'Contents'
)).
createSync
(
recursive:
true
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
home
,
'Applications'
,
'Visual Studio Code - Insiders.app'
,
'Contents'
)).
createSync
(
recursive:
true
);
final
FakeProcessManager
processManager
=
FakeProcessManager
.
list
(<
FakeCommand
>[
FakeCommand
(
command:
const
<
String
>[
'mdfind'
,
'kMDItemCFBundleIdentifier="com.microsoft.VSCode"'
,
],
stdout:
randomLocation
,
),
FakeCommand
(
command:
const
<
String
>[
'mdfind'
,
'kMDItemCFBundleIdentifier="com.microsoft.VSCodeInsiders"'
,
],
stdout:
randomInsidersLocation
,
),
]);
final
List
<
VsCode
>
installed
=
VsCode
.
allInstalled
(
fileSystem
,
platform
,
processManager
);
// Finds three non-Insider installations.
expect
(
installed
.
length
,
3
);
expect
(
processManager
,
hasNoRemainingExpectations
);
});
}
packages/flutter_tools/test/general.shard/vscode/vscode_validator_test.dart
View file @
7aa188ba
...
...
@@ -8,6 +8,7 @@ import 'package:flutter_tools/src/base/platform.dart';
import
'package:flutter_tools/src/vscode/vscode.dart'
;
import
'../../src/common.dart'
;
import
'../../src/fake_process_manager.dart'
;
void
main
(
)
{
testWithoutContext
(
'VsCode search locations on windows supports an empty environment'
,
()
{
...
...
@@ -17,6 +18,6 @@ void main() {
environment:
<
String
,
String
>{},
);
expect
(
VsCode
.
allInstalled
(
fileSystem
,
platform
),
isEmpty
);
expect
(
VsCode
.
allInstalled
(
fileSystem
,
platform
,
FakeProcessManager
.
any
()
),
isEmpty
);
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment