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
b2800748
Unverified
Commit
b2800748
authored
Aug 02, 2018
by
Mikkel Nygaard Ravn
Committed by
GitHub
Aug 02, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move async from member access to construction (#20035)
parent
eda03e25
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
174 additions
and
166 deletions
+174
-166
android_device.dart
packages/flutter_tools/lib/src/android/android_device.dart
+3
-2
gradle.dart
packages/flutter_tools/lib/src/android/gradle.dart
+3
-3
application_package.dart
packages/flutter_tools/lib/src/application_package.dart
+2
-2
build_apk.dart
packages/flutter_tools/lib/src/commands/build_apk.dart
+5
-2
create.dart
packages/flutter_tools/lib/src/commands/create.dart
+25
-22
inject_plugins.dart
packages/flutter_tools/lib/src/commands/inject_plugins.dart
+1
-2
packages.dart
packages/flutter_tools/lib/src/commands/packages.dart
+1
-1
flutter_manifest.dart
packages/flutter_tools/lib/src/flutter_manifest.dart
+8
-0
mac.dart
packages/flutter_tools/lib/src/ios/mac.dart
+1
-1
xcodeproj.dart
packages/flutter_tools/lib/src/ios/xcodeproj.dart
+4
-4
plugins.dart
packages/flutter_tools/lib/src/plugins.dart
+3
-3
project.dart
packages/flutter_tools/lib/src/project.dart
+72
-83
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+4
-4
flutter_command.dart
packages/flutter_tools/lib/src/runner/flutter_command.dart
+2
-1
gradle_test.dart
packages/flutter_tools/test/android/gradle_test.dart
+4
-2
create_test.dart
packages/flutter_tools/test/commands/create_test.dart
+4
-2
cocoapods_test.dart
packages/flutter_tools/test/ios/cocoapods_test.dart
+6
-6
xcodeproj_test.dart
packages/flutter_tools/test/ios/xcodeproj_test.dart
+5
-5
project_test.dart
packages/flutter_tools/test/project_test.dart
+21
-21
No files found.
packages/flutter_tools/lib/src/android/android_device.dart
View file @
b2800748
...
@@ -375,14 +375,15 @@ class AndroidDevice extends Device {
...
@@ -375,14 +375,15 @@ class AndroidDevice extends Device {
if
(!
prebuiltApplication
)
{
if
(!
prebuiltApplication
)
{
printTrace
(
'Building APK'
);
printTrace
(
'Building APK'
);
final
FlutterProject
project
=
await
FlutterProject
.
current
();
await
buildApk
(
await
buildApk
(
project:
new
FlutterProject
(
fs
.
currentDirectory
)
,
project:
project
,
target:
mainPath
,
target:
mainPath
,
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
);
);
// Package has been built, so we can get the updated application ID and
// Package has been built, so we can get the updated application ID and
// activity name from the .apk.
// activity name from the .apk.
package
=
await
AndroidApk
.
fromAndroidProject
(
new
FlutterProject
(
fs
.
currentDirectory
)
.
android
);
package
=
await
AndroidApk
.
fromAndroidProject
(
project
.
android
);
}
}
printTrace
(
"Stopping app '
${package.name}
' on
$name
."
);
printTrace
(
"Stopping app '
${package.name}
' on
$name
."
);
...
...
packages/flutter_tools/lib/src/android/gradle.dart
View file @
b2800748
...
@@ -90,7 +90,7 @@ Future<GradleProject> _gradleProject() async {
...
@@ -90,7 +90,7 @@ Future<GradleProject> _gradleProject() async {
// Note: Dependencies are resolved and possibly downloaded as a side-effect
// Note: Dependencies are resolved and possibly downloaded as a side-effect
// of calculating the app properties using Gradle. This may take minutes.
// of calculating the app properties using Gradle. This may take minutes.
Future
<
GradleProject
>
_readGradleProject
()
async
{
Future
<
GradleProject
>
_readGradleProject
()
async
{
final
FlutterProject
flutterProject
=
new
FlutterProject
(
fs
.
currentDirectory
);
final
FlutterProject
flutterProject
=
await
FlutterProject
.
current
(
);
final
String
gradle
=
await
_ensureGradle
(
flutterProject
);
final
String
gradle
=
await
_ensureGradle
(
flutterProject
);
await
updateLocalProperties
(
project:
flutterProject
);
await
updateLocalProperties
(
project:
flutterProject
);
final
Status
status
=
logger
.
startProgress
(
'Resolving dependencies...'
,
expectSlowOperation:
true
);
final
Status
status
=
logger
.
startProgress
(
'Resolving dependencies...'
,
expectSlowOperation:
true
);
...
@@ -214,7 +214,7 @@ Future<void> updateLocalProperties({
...
@@ -214,7 +214,7 @@ Future<void> updateLocalProperties({
throwToolExit
(
'Unable to locate Android SDK. Please run `flutter doctor` for more details.'
);
throwToolExit
(
'Unable to locate Android SDK. Please run `flutter doctor` for more details.'
);
}
}
final
File
localProperties
=
await
project
.
androidLocalPropertiesFile
;
final
File
localProperties
=
project
.
androidLocalPropertiesFile
;
bool
changed
=
false
;
bool
changed
=
false
;
SettingsFile
settings
;
SettingsFile
settings
;
...
@@ -232,7 +232,7 @@ Future<void> updateLocalProperties({
...
@@ -232,7 +232,7 @@ Future<void> updateLocalProperties({
}
}
}
}
final
FlutterManifest
manifest
=
await
project
.
manifest
;
final
FlutterManifest
manifest
=
project
.
manifest
;
if
(
androidSdk
!=
null
)
if
(
androidSdk
!=
null
)
changeIfNecessary
(
'sdk.dir'
,
escapePath
(
androidSdk
.
directory
));
changeIfNecessary
(
'sdk.dir'
,
escapePath
(
androidSdk
.
directory
));
...
...
packages/flutter_tools/lib/src/application_package.dart
View file @
b2800748
...
@@ -314,7 +314,7 @@ Future<ApplicationPackage> getApplicationPackageForPlatform(
...
@@ -314,7 +314,7 @@ Future<ApplicationPackage> getApplicationPackageForPlatform(
case
TargetPlatform
.
android_x64
:
case
TargetPlatform
.
android_x64
:
case
TargetPlatform
.
android_x86
:
case
TargetPlatform
.
android_x86
:
return
applicationBinary
==
null
return
applicationBinary
==
null
?
await
AndroidApk
.
fromAndroidProject
(
new
FlutterProject
(
fs
.
currentDirectory
).
android
)
?
await
AndroidApk
.
fromAndroidProject
(
(
await
FlutterProject
.
current
()
).
android
)
:
new
AndroidApk
.
fromApk
(
applicationBinary
);
:
new
AndroidApk
.
fromApk
(
applicationBinary
);
case
TargetPlatform
.
ios
:
case
TargetPlatform
.
ios
:
return
applicationBinary
==
null
return
applicationBinary
==
null
...
@@ -344,7 +344,7 @@ class ApplicationPackageStore {
...
@@ -344,7 +344,7 @@ class ApplicationPackageStore {
case
TargetPlatform
.
android_arm64
:
case
TargetPlatform
.
android_arm64
:
case
TargetPlatform
.
android_x64
:
case
TargetPlatform
.
android_x64
:
case
TargetPlatform
.
android_x86
:
case
TargetPlatform
.
android_x86
:
android
??=
await
AndroidApk
.
fromAndroidProject
(
new
FlutterProject
(
fs
.
currentDirectory
).
android
);
android
??=
await
AndroidApk
.
fromAndroidProject
(
(
await
FlutterProject
.
current
()
).
android
);
return
android
;
return
android
;
case
TargetPlatform
.
ios
:
case
TargetPlatform
.
ios
:
iOS
??=
new
IOSApp
.
fromCurrentDirectory
();
iOS
??=
new
IOSApp
.
fromCurrentDirectory
();
...
...
packages/flutter_tools/lib/src/commands/build_apk.dart
View file @
b2800748
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
import
'dart:async'
;
import
'dart:async'
;
import
'../android/apk.dart'
;
import
'../android/apk.dart'
;
import
'../base/file_system.dart'
;
import
'../project.dart'
;
import
'../project.dart'
;
import
'build.dart'
;
import
'build.dart'
;
...
@@ -46,6 +45,10 @@ class BuildApkCommand extends BuildSubCommand {
...
@@ -46,6 +45,10 @@ class BuildApkCommand extends BuildSubCommand {
@override
@override
Future
<
Null
>
runCommand
()
async
{
Future
<
Null
>
runCommand
()
async
{
await
super
.
runCommand
();
await
super
.
runCommand
();
await
buildApk
(
project:
new
FlutterProject
(
fs
.
currentDirectory
),
target:
targetFile
,
buildInfo:
getBuildInfo
());
await
buildApk
(
project:
await
FlutterProject
.
current
(),
target:
targetFile
,
buildInfo:
getBuildInfo
(),
);
}
}
}
}
packages/flutter_tools/lib/src/commands/create.dart
View file @
b2800748
...
@@ -135,7 +135,8 @@ class CreateCommand extends FlutterCommand {
...
@@ -135,7 +135,8 @@ class CreateCommand extends FlutterCommand {
dirPath
=
fs
.
path
.
dirname
(
dirPath
);
dirPath
=
fs
.
path
.
dirname
(
dirPath
);
String
organization
=
argResults
[
'org'
];
String
organization
=
argResults
[
'org'
];
if
(!
argResults
.
wasParsed
(
'org'
))
{
if
(!
argResults
.
wasParsed
(
'org'
))
{
final
Set
<
String
>
existingOrganizations
=
await
new
FlutterProject
(
projectDir
).
organizationNames
();
final
FlutterProject
project
=
await
FlutterProject
.
fromDirectory
(
projectDir
);
final
Set
<
String
>
existingOrganizations
=
await
project
.
organizationNames
();
if
(
existingOrganizations
.
length
==
1
)
{
if
(
existingOrganizations
.
length
==
1
)
{
organization
=
existingOrganizations
.
first
;
organization
=
existingOrganizations
.
first
;
}
else
if
(
1
<
existingOrganizations
.
length
)
{
}
else
if
(
1
<
existingOrganizations
.
length
)
{
...
@@ -167,20 +168,20 @@ class CreateCommand extends FlutterCommand {
...
@@ -167,20 +168,20 @@ class CreateCommand extends FlutterCommand {
);
);
printStatus
(
'Creating project
${fs.path.relative(dirPath)}
...'
);
printStatus
(
'Creating project
${fs.path.relative(dirPath)}
...'
);
final
Directory
directory
=
fs
.
directory
(
dirPath
);
int
generatedFileCount
=
0
;
int
generatedFileCount
=
0
;
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
dirPath
);
switch
(
template
)
{
switch
(
template
)
{
case
'app'
:
case
'app'
:
generatedFileCount
+=
await
_generateApp
(
project
,
templateContext
);
generatedFileCount
+=
await
_generateApp
(
directory
,
templateContext
);
break
;
break
;
case
'module'
:
case
'module'
:
generatedFileCount
+=
await
_generateModule
(
project
,
templateContext
);
generatedFileCount
+=
await
_generateModule
(
directory
,
templateContext
);
break
;
break
;
case
'package'
:
case
'package'
:
generatedFileCount
+=
await
_generatePackage
(
project
,
templateContext
);
generatedFileCount
+=
await
_generatePackage
(
directory
,
templateContext
);
break
;
break
;
case
'plugin'
:
case
'plugin'
:
generatedFileCount
+=
await
_generatePlugin
(
project
,
templateContext
);
generatedFileCount
+=
await
_generatePlugin
(
directory
,
templateContext
);
break
;
break
;
}
}
printStatus
(
'Wrote
$generatedFileCount
files.'
);
printStatus
(
'Wrote
$generatedFileCount
files.'
);
...
@@ -193,6 +194,7 @@ class CreateCommand extends FlutterCommand {
...
@@ -193,6 +194,7 @@ class CreateCommand extends FlutterCommand {
printStatus
(
'Your module code is in lib/main.dart in the
$relativePath
directory.'
);
printStatus
(
'Your module code is in lib/main.dart in the
$relativePath
directory.'
);
}
else
{
}
else
{
// Run doctor; tell the user the next steps.
// Run doctor; tell the user the next steps.
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
dirPath
);
final
FlutterProject
app
=
project
.
hasExampleApp
?
project
.
example
:
project
;
final
FlutterProject
app
=
project
.
hasExampleApp
?
project
.
example
:
project
;
final
String
relativeAppPath
=
fs
.
path
.
relative
(
app
.
directory
.
path
);
final
String
relativeAppPath
=
fs
.
path
.
relative
(
app
.
directory
.
path
);
final
String
relativePluginPath
=
fs
.
path
.
relative
(
dirPath
);
final
String
relativePluginPath
=
fs
.
path
.
relative
(
dirPath
);
...
@@ -233,57 +235,57 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
...
@@ -233,57 +235,57 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
}
}
}
}
Future
<
int
>
_generateModule
(
FlutterProject
project
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
Future
<
int
>
_generateModule
(
Directory
directory
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
int
generatedCount
=
0
;
int
generatedCount
=
0
;
final
String
description
=
argResults
.
wasParsed
(
'description'
)
final
String
description
=
argResults
.
wasParsed
(
'description'
)
?
argResults
[
'description'
]
?
argResults
[
'description'
]
:
'A new flutter module project.'
;
:
'A new flutter module project.'
;
templateContext
[
'description'
]
=
description
;
templateContext
[
'description'
]
=
description
;
generatedCount
+=
_renderTemplate
(
fs
.
path
.
join
(
'module'
,
'common'
),
project
.
directory
,
templateContext
);
generatedCount
+=
_renderTemplate
(
fs
.
path
.
join
(
'module'
,
'common'
),
directory
,
templateContext
);
if
(
argResults
[
'pub'
])
{
if
(
argResults
[
'pub'
])
{
await
pubGet
(
await
pubGet
(
context:
PubContext
.
create
,
context:
PubContext
.
create
,
directory:
project
.
directory
.
path
,
directory:
directory
.
path
,
offline:
argResults
[
'offline'
],
offline:
argResults
[
'offline'
],
);
);
final
FlutterProject
project
=
await
FlutterProject
.
fromDirectory
(
directory
);
await
project
.
ensureReadyForPlatformSpecificTooling
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
}
}
return
generatedCount
;
return
generatedCount
;
}
}
Future
<
int
>
_generatePackage
(
FlutterProject
project
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
Future
<
int
>
_generatePackage
(
Directory
directory
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
int
generatedCount
=
0
;
int
generatedCount
=
0
;
final
String
description
=
argResults
.
wasParsed
(
'description'
)
final
String
description
=
argResults
.
wasParsed
(
'description'
)
?
argResults
[
'description'
]
?
argResults
[
'description'
]
:
'A new flutter package project.'
;
:
'A new flutter package project.'
;
templateContext
[
'description'
]
=
description
;
templateContext
[
'description'
]
=
description
;
generatedCount
+=
_renderTemplate
(
'package'
,
project
.
directory
,
templateContext
);
generatedCount
+=
_renderTemplate
(
'package'
,
directory
,
templateContext
);
if
(
argResults
[
'pub'
])
{
if
(
argResults
[
'pub'
])
{
await
pubGet
(
await
pubGet
(
context:
PubContext
.
createPackage
,
context:
PubContext
.
createPackage
,
directory:
project
.
directory
.
path
,
directory:
directory
.
path
,
offline:
argResults
[
'offline'
],
offline:
argResults
[
'offline'
],
);
);
}
}
return
generatedCount
;
return
generatedCount
;
}
}
Future
<
int
>
_generatePlugin
(
FlutterProject
project
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
Future
<
int
>
_generatePlugin
(
Directory
directory
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
int
generatedCount
=
0
;
int
generatedCount
=
0
;
final
String
description
=
argResults
.
wasParsed
(
'description'
)
final
String
description
=
argResults
.
wasParsed
(
'description'
)
?
argResults
[
'description'
]
?
argResults
[
'description'
]
:
'A new flutter plugin project.'
;
:
'A new flutter plugin project.'
;
templateContext
[
'description'
]
=
description
;
templateContext
[
'description'
]
=
description
;
generatedCount
+=
_renderTemplate
(
'plugin'
,
project
.
directory
,
templateContext
);
generatedCount
+=
_renderTemplate
(
'plugin'
,
directory
,
templateContext
);
if
(
argResults
[
'pub'
])
{
if
(
argResults
[
'pub'
])
{
await
pubGet
(
await
pubGet
(
context:
PubContext
.
createPlugin
,
context:
PubContext
.
createPlugin
,
directory:
project
.
directory
.
path
,
directory:
directory
.
path
,
offline:
argResults
[
'offline'
],
offline:
argResults
[
'offline'
],
);
);
}
}
final
FlutterProject
project
=
await
FlutterProject
.
fromDirectory
(
directory
);
if
(
android_sdk
.
androidSdk
!=
null
)
if
(
android_sdk
.
androidSdk
!=
null
)
await
gradle
.
updateLocalProperties
(
project:
project
);
await
gradle
.
updateLocalProperties
(
project:
project
);
...
@@ -298,22 +300,23 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
...
@@ -298,22 +300,23 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
templateContext
[
'pluginProjectName'
]
=
projectName
;
templateContext
[
'pluginProjectName'
]
=
projectName
;
templateContext
[
'androidPluginIdentifier'
]
=
androidPluginIdentifier
;
templateContext
[
'androidPluginIdentifier'
]
=
androidPluginIdentifier
;
generatedCount
+=
await
_generateApp
(
project
.
example
,
templateContext
);
generatedCount
+=
await
_generateApp
(
project
.
example
.
directory
,
templateContext
);
return
generatedCount
;
return
generatedCount
;
}
}
Future
<
int
>
_generateApp
(
FlutterProject
project
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
Future
<
int
>
_generateApp
(
Directory
directory
,
Map
<
String
,
dynamic
>
templateContext
)
async
{
int
generatedCount
=
0
;
int
generatedCount
=
0
;
generatedCount
+=
_renderTemplate
(
'create'
,
project
.
directory
,
templateContext
);
generatedCount
+=
_renderTemplate
(
'create'
,
directory
,
templateContext
);
final
FlutterProject
project
=
await
FlutterProject
.
fromDirectory
(
directory
);
generatedCount
+=
_injectGradleWrapper
(
project
);
generatedCount
+=
_injectGradleWrapper
(
project
);
if
(
argResults
[
'with-driver-test'
])
{
if
(
argResults
[
'with-driver-test'
])
{
final
Directory
testDirectory
=
project
.
directory
.
childDirectory
(
'test_driver'
);
final
Directory
testDirectory
=
directory
.
childDirectory
(
'test_driver'
);
generatedCount
+=
_renderTemplate
(
'driver'
,
testDirectory
,
templateContext
);
generatedCount
+=
_renderTemplate
(
'driver'
,
testDirectory
,
templateContext
);
}
}
if
(
argResults
[
'pub'
])
{
if
(
argResults
[
'pub'
])
{
await
pubGet
(
context:
PubContext
.
create
,
directory:
project
.
directory
.
path
,
offline:
argResults
[
'offline'
]);
await
pubGet
(
context:
PubContext
.
create
,
directory:
directory
.
path
,
offline:
argResults
[
'offline'
]);
await
project
.
ensureReadyForPlatformSpecificTooling
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
}
}
...
...
packages/flutter_tools/lib/src/commands/inject_plugins.dart
View file @
b2800748
...
@@ -4,7 +4,6 @@
...
@@ -4,7 +4,6 @@
import
'dart:async'
;
import
'dart:async'
;
import
'../base/file_system.dart'
;
import
'../globals.dart'
;
import
'../globals.dart'
;
import
'../plugins.dart'
;
import
'../plugins.dart'
;
import
'../project.dart'
;
import
'../project.dart'
;
...
@@ -26,7 +25,7 @@ class InjectPluginsCommand extends FlutterCommand {
...
@@ -26,7 +25,7 @@ class InjectPluginsCommand extends FlutterCommand {
@override
@override
Future
<
Null
>
runCommand
()
async
{
Future
<
Null
>
runCommand
()
async
{
final
FlutterProject
project
=
new
FlutterProject
(
fs
.
currentDirectory
);
final
FlutterProject
project
=
await
FlutterProject
.
current
(
);
await
injectPlugins
(
project
);
await
injectPlugins
(
project
);
final
bool
result
=
hasPlugins
(
project
);
final
bool
result
=
hasPlugins
(
project
);
if
(
result
)
{
if
(
result
)
{
...
...
packages/flutter_tools/lib/src/commands/packages.dart
View file @
b2800748
...
@@ -80,7 +80,7 @@ class PackagesGetCommand extends FlutterCommand {
...
@@ -80,7 +80,7 @@ class PackagesGetCommand extends FlutterCommand {
}
}
await
_runPubGet
(
target
);
await
_runPubGet
(
target
);
final
FlutterProject
rootProject
=
new
FlutterProject
.
fromPath
(
target
);
final
FlutterProject
rootProject
=
await
FlutterProject
.
fromPath
(
target
);
await
rootProject
.
ensureReadyForPlatformSpecificTooling
();
await
rootProject
.
ensureReadyForPlatformSpecificTooling
();
// Get/upgrade packages in example app as well
// Get/upgrade packages in example app as well
...
...
packages/flutter_tools/lib/src/flutter_manifest.dart
View file @
b2800748
...
@@ -20,6 +20,14 @@ final RegExp _versionPattern = new RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?(\+(\d+))?
...
@@ -20,6 +20,14 @@ final RegExp _versionPattern = new RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?(\+(\d+))?
class
FlutterManifest
{
class
FlutterManifest
{
FlutterManifest
.
_
();
FlutterManifest
.
_
();
/// Returns an empty manifest.
static
FlutterManifest
empty
()
{
final
FlutterManifest
manifest
=
new
FlutterManifest
.
_
();
manifest
.
_descriptor
=
<
String
,
dynamic
>{};
manifest
.
_flutterDescriptor
=
<
String
,
dynamic
>{};
return
manifest
;
}
/// Returns null on invalid manifest. Returns empty manifest on missing file.
/// Returns null on invalid manifest. Returns empty manifest on missing file.
static
Future
<
FlutterManifest
>
createFromPath
(
String
path
)
async
{
static
Future
<
FlutterManifest
>
createFromPath
(
String
path
)
async
{
if
(
path
==
null
||
!
fs
.
isFileSync
(
path
))
if
(
path
==
null
||
!
fs
.
isFileSync
(
path
))
...
...
packages/flutter_tools/lib/src/ios/mac.dart
View file @
b2800748
...
@@ -233,7 +233,7 @@ Future<XcodeBuildResult> buildXcodeProject({
...
@@ -233,7 +233,7 @@ Future<XcodeBuildResult> buildXcodeProject({
final
Directory
appDirectory
=
fs
.
directory
(
app
.
appDirectory
);
final
Directory
appDirectory
=
fs
.
directory
(
app
.
appDirectory
);
await
_addServicesToBundle
(
appDirectory
);
await
_addServicesToBundle
(
appDirectory
);
final
FlutterProject
project
=
new
FlutterProject
(
fs
.
currentDirectory
);
final
FlutterProject
project
=
await
FlutterProject
.
current
(
);
await
updateGeneratedXcodeProperties
(
await
updateGeneratedXcodeProperties
(
project:
project
,
project:
project
,
targetOverride:
targetOverride
,
targetOverride:
targetOverride
,
...
...
packages/flutter_tools/lib/src/ios/xcodeproj.dart
View file @
b2800748
...
@@ -32,9 +32,9 @@ String flutterFrameworkDir(BuildMode mode) {
...
@@ -32,9 +32,9 @@ String flutterFrameworkDir(BuildMode mode) {
/// if project is an iOS project and such files are out of date or do not
/// if project is an iOS project and such files are out of date or do not
/// already exist.
/// already exist.
Future
<
void
>
generateXcodeProperties
({
FlutterProject
project
})
async
{
Future
<
void
>
generateXcodeProperties
({
FlutterProject
project
})
async
{
if
(
(
await
project
.
manifest
)
.
isModule
||
if
(
project
.
manifest
.
isModule
||
project
.
ios
.
directory
.
existsSync
())
{
project
.
ios
.
directory
.
existsSync
())
{
if
(!
Cache
.
instance
.
fileOlderThanToolsStamp
(
await
project
.
generatedXcodePropertiesFile
))
{
if
(!
Cache
.
instance
.
fileOlderThanToolsStamp
(
project
.
generatedXcodePropertiesFile
))
{
return
;
return
;
}
}
...
@@ -79,7 +79,7 @@ Future<void> updateGeneratedXcodeProperties({
...
@@ -79,7 +79,7 @@ Future<void> updateGeneratedXcodeProperties({
localsBuffer
.
writeln
(
'SYMROOT=
\
${SOURCE_ROOT}
/../
${getIosBuildDirectory()}
'
);
localsBuffer
.
writeln
(
'SYMROOT=
\
${SOURCE_ROOT}
/../
${getIosBuildDirectory()}
'
);
final
FlutterManifest
manifest
=
await
project
.
manifest
;
final
FlutterManifest
manifest
=
project
.
manifest
;
if
(!
manifest
.
isModule
)
{
if
(!
manifest
.
isModule
)
{
// For module projects we do not want to write the FLUTTER_FRAMEWORK_DIR
// For module projects we do not want to write the FLUTTER_FRAMEWORK_DIR
// explicitly. Rather we rely on the xcode backend script and the Podfile
// explicitly. Rather we rely on the xcode backend script and the Podfile
...
@@ -119,7 +119,7 @@ Future<void> updateGeneratedXcodeProperties({
...
@@ -119,7 +119,7 @@ Future<void> updateGeneratedXcodeProperties({
localsBuffer
.
writeln
(
'TRACK_WIDGET_CREATION=true'
);
localsBuffer
.
writeln
(
'TRACK_WIDGET_CREATION=true'
);
}
}
final
File
generatedXcodePropertiesFile
=
await
project
.
generatedXcodePropertiesFile
;
final
File
generatedXcodePropertiesFile
=
project
.
generatedXcodePropertiesFile
;
generatedXcodePropertiesFile
.
createSync
(
recursive:
true
);
generatedXcodePropertiesFile
.
createSync
(
recursive:
true
);
generatedXcodePropertiesFile
.
writeAsStringSync
(
localsBuffer
.
toString
());
generatedXcodePropertiesFile
.
writeAsStringSync
(
localsBuffer
.
toString
());
}
}
...
...
packages/flutter_tools/lib/src/plugins.dart
View file @
b2800748
...
@@ -158,7 +158,7 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
...
@@ -158,7 +158,7 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
};
};
final
String
javaSourcePath
=
fs
.
path
.
join
(
final
String
javaSourcePath
=
fs
.
path
.
join
(
(
await
project
.
androidPluginRegistrantHost
)
.
path
,
project
.
androidPluginRegistrantHost
.
path
,
'src'
,
'src'
,
'main'
,
'main'
,
'java'
,
'java'
,
...
@@ -247,8 +247,8 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug
...
@@ -247,8 +247,8 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug
'plugins'
:
iosPlugins
,
'plugins'
:
iosPlugins
,
};
};
final
String
registryDirectory
=
(
await
project
.
iosPluginRegistrantHost
)
.
path
;
final
String
registryDirectory
=
project
.
iosPluginRegistrantHost
.
path
;
if
(
(
await
project
.
manifest
)
.
isModule
)
{
if
(
project
.
manifest
.
isModule
)
{
final
String
registryClassesDirectory
=
fs
.
path
.
join
(
registryDirectory
,
'Classes'
);
final
String
registryClassesDirectory
=
fs
.
path
.
join
(
registryDirectory
,
'Classes'
);
_renderTemplateToFile
(
_renderTemplateToFile
(
_iosPluginRegistrantPodspecTemplate
,
_iosPluginRegistrantPodspecTemplate
,
...
...
packages/flutter_tools/lib/src/project.dart
View file @
b2800748
...
@@ -15,20 +15,39 @@ import 'plugins.dart';
...
@@ -15,20 +15,39 @@ import 'plugins.dart';
import
'template.dart'
;
import
'template.dart'
;
/// Represents the contents of a Flutter project at the specified [directory].
/// Represents the contents of a Flutter project at the specified [directory].
///
/// Instances should be treated as immutable snapshots, to be replaced by new
/// instances on changes to `pubspec.yaml` files.
class
FlutterProject
{
class
FlutterProject
{
FlutterProject
.
_
(
this
.
directory
,
this
.
manifest
,
this
.
_exampleManifest
);
/// Returns a future that completes with a FlutterProject view of the given directory.
static
Future
<
FlutterProject
>
fromDirectory
(
Directory
directory
)
async
{
final
FlutterManifest
manifest
=
await
FlutterManifest
.
createFromPath
(
directory
.
childFile
(
bundle
.
defaultManifestPath
).
path
,
);
final
Directory
exampleDirectory
=
directory
.
childDirectory
(
'example'
);
final
FlutterManifest
exampleManifest
=
await
FlutterManifest
.
createFromPath
(
exampleDirectory
.
childFile
(
bundle
.
defaultManifestPath
).
path
,
);
return
new
FlutterProject
.
_
(
directory
,
manifest
,
exampleManifest
);
}
FlutterProject
(
this
.
directory
);
/// Returns a future that completes with a FlutterProject view of the current directory.
FlutterProject
.
fromPath
(
String
projectPath
)
:
directory
=
fs
.
directory
(
projectPath
);
static
Future
<
FlutterProject
>
current
()
=>
fromDirectory
(
fs
.
currentDirectory
);
/// Returns a future that completes with a FlutterProject view of the given directory.
static
Future
<
FlutterProject
>
fromPath
(
String
path
)
=>
fromDirectory
(
fs
.
directory
(
path
));
/// The location of this project.
/// The location of this project.
final
Directory
directory
;
final
Directory
directory
;
Future
<
FlutterManifest
>
get
manifest
{
/// The manifest of this project, or null, if `pubspec.yaml` is invalid.
return
_manifest
??=
FlutterManifest
.
createFromPath
(
final
FlutterManifest
manifest
;
directory
.
childFile
(
bundle
.
defaultManifestPath
).
path
,
);
/// The manifest of the example sub-project of this project, or null, if
}
/// `example/pubspec.yaml` is invalid.
Future
<
FlutterManifest
>
_m
anifest
;
final
FlutterManifest
_exampleM
anifest
;
/// Asynchronously returns the organization names found in this project as
/// Asynchronously returns the organization names found in this project as
/// part of iOS product bundle identifier, Android application ID, or
/// part of iOS product bundle identifier, Android application ID, or
...
@@ -41,10 +60,9 @@ class FlutterProject {
...
@@ -41,10 +60,9 @@ class FlutterProject {
example
.
android
.
applicationId
(),
example
.
android
.
applicationId
(),
example
.
ios
.
productBundleIdentifier
(),
example
.
ios
.
productBundleIdentifier
(),
]);
]);
return
new
Set
<
String
>.
from
(
return
new
Set
<
String
>.
from
(
candidates
candidates
.
map
(
_organizationNameFromPackageName
)
.
map
(
_organizationNameFromPackageName
)
.
where
((
String
name
)
=>
name
!=
null
)
.
where
((
String
name
)
=>
name
!=
null
));
);
}
}
String
_organizationNameFromPackageName
(
String
packageName
)
{
String
_organizationNameFromPackageName
(
String
packageName
)
{
...
@@ -66,75 +84,52 @@ class FlutterProject {
...
@@ -66,75 +84,52 @@ class FlutterProject {
/// The generated IosModule sub project of this module project.
/// The generated IosModule sub project of this module project.
IosModuleProject
get
iosModule
=>
new
IosModuleProject
(
directory
.
childDirectory
(
'.ios'
));
IosModuleProject
get
iosModule
=>
new
IosModuleProject
(
directory
.
childDirectory
(
'.ios'
));
Future
<
File
>
get
androidLocalPropertiesFile
{
File
get
androidLocalPropertiesFile
{
return
_androidLocalPropertiesFile
??=
manifest
.
then
<
File
>((
FlutterManifest
manifest
)
{
return
directory
return
directory
.
childDirectory
(
manifest
.
isModule
?
'.android'
:
'android'
)
.
childDirectory
(
manifest
.
isModule
?
'.android'
:
'android'
)
.
childFile
(
'local.properties'
);
.
childFile
(
'local.properties'
);
});
}
}
Future
<
File
>
_androidLocalPropertiesFile
;
Future
<
File
>
get
generatedXcodePropertiesFile
{
return
_generatedXcodeProperties
??=
manifest
.
then
<
File
>((
FlutterManifest
manifest
)
{
return
directory
.
childDirectory
(
manifest
.
isModule
?
'.ios'
:
'ios'
)
.
childDirectory
(
'Flutter'
)
.
childFile
(
'Generated.xcconfig'
);
});
}
Future
<
File
>
_generatedXcodeProperties
;
File
get
flutterPluginsFile
{
File
get
generatedXcodePropertiesFile
{
return
_flutterPluginsFile
??=
directory
.
childFile
(
'.flutter-plugins'
);
return
directory
.
childDirectory
(
manifest
.
isModule
?
'.ios'
:
'ios'
)
.
childDirectory
(
'Flutter'
)
.
childFile
(
'Generated.xcconfig'
);
}
}
File
_flutterPluginsFile
;
File
get
flutterPluginsFile
=>
directory
.
childFile
(
'.flutter-plugins'
);
Future
<
Directory
>
get
androidPluginRegistrantHost
async
{
return
_androidPluginRegistrantHost
??=
manifest
.
then
((
FlutterManifest
manifest
)
{
Directory
get
androidPluginRegistrantHost
{
if
(
manifest
.
isModule
)
{
return
manifest
.
isModule
return
directory
.
childDirectory
(
'.android'
).
childDirectory
(
'Flutter'
);
?
directory
.
childDirectory
(
'.android'
).
childDirectory
(
'Flutter'
)
}
else
{
:
directory
.
childDirectory
(
'android'
).
childDirectory
(
'app'
);
return
directory
.
childDirectory
(
'android'
).
childDirectory
(
'app'
);
}
});
}
}
Future
<
Directory
>
_androidPluginRegistrantHost
;
Directory
get
iosPluginRegistrantHost
{
Future
<
Directory
>
get
iosPluginRegistrantHost
async
{
// In a module create the GeneratedPluginRegistrant as a pod to be included
return
_iosPluginRegistrantHost
??=
manifest
.
then
((
FlutterManifest
manifest
)
{
// from a hosting app.
if
(
manifest
.
isModule
)
{
// For a non-module create the GeneratedPluginRegistrant as source files
// In a module create the GeneratedPluginRegistrant as a pod to be included
// directly in the iOS project.
// from a hosting app.
return
manifest
.
isModule
return
directory
?
directory
.
childDirectory
(
'.ios'
).
childDirectory
(
'Flutter'
).
childDirectory
(
'FlutterPluginRegistrant'
)
.
childDirectory
(
'.ios'
)
:
directory
.
childDirectory
(
'ios'
).
childDirectory
(
'Runner'
);
.
childDirectory
(
'Flutter'
)
.
childDirectory
(
'FlutterPluginRegistrant'
);
}
else
{
// For a non-module create the GeneratedPluginRegistrant as source files
// directly in the iOS project.
return
directory
.
childDirectory
(
'ios'
).
childDirectory
(
'Runner'
);
}
});
}
}
Future
<
Directory
>
_iosPluginRegistrantHost
;
///
Returns true if this project has an example application
///
The example sub-project of this project.
bool
get
hasExampleApp
=>
_exampleDirectory
.
childFile
(
'pubspec.yaml'
).
existsSync
(
);
FlutterProject
get
example
=>
new
FlutterProject
.
_
(
_exampleDirectory
,
_exampleManifest
,
FlutterManifest
.
empty
()
);
/// T
he example sub project of this (package or plugin) project.
/// T
rue, if this project has an example application
FlutterProject
get
example
=>
new
FlutterProject
(
_exampleDirectory
);
bool
get
hasExampleApp
=>
_exampleDirectory
.
childFile
(
'pubspec.yaml'
).
existsSync
(
);
/// The directory that will contain the example if an example exists.
/// The directory that will contain the example if an example exists.
Directory
get
_exampleDirectory
=>
directory
.
childDirectory
(
'example'
);
Directory
get
_exampleDirectory
=>
directory
.
childDirectory
(
'example'
);
/// Generates project files necessary to make Gradle builds work on Android
/// Generates project files necessary to make Gradle builds work on Android
/// and CocoaPods+Xcode work on iOS, for app and module projects only.
/// and CocoaPods+Xcode work on iOS, for app and module projects only.
///
/// Returns the number of files written.
Future
<
void
>
ensureReadyForPlatformSpecificTooling
()
async
{
Future
<
void
>
ensureReadyForPlatformSpecificTooling
()
async
{
if
(!
directory
.
existsSync
()
||
hasExampleApp
)
{
if
(!
directory
.
existsSync
()
||
hasExampleApp
)
{
return
0
;
return
;
}
}
final
FlutterManifest
manifest
=
await
this
.
manifest
;
if
(
manifest
.
isModule
)
{
if
(
manifest
.
isModule
)
{
await
androidModule
.
ensureReadyForPlatformSpecificTooling
(
this
);
await
androidModule
.
ensureReadyForPlatformSpecificTooling
(
this
);
await
iosModule
.
ensureReadyForPlatformSpecificTooling
();
await
iosModule
.
ensureReadyForPlatformSpecificTooling
();
...
@@ -152,9 +147,7 @@ class IosProject {
...
@@ -152,9 +147,7 @@ class IosProject {
final
Directory
directory
;
final
Directory
directory
;
/// The xcode config file for [mode].
/// The xcode config file for [mode].
File
xcodeConfigFor
(
String
mode
)
{
File
xcodeConfigFor
(
String
mode
)
=>
directory
.
childDirectory
(
'Flutter'
).
childFile
(
'
$mode
.xcconfig'
);
return
directory
.
childDirectory
(
'Flutter'
).
childFile
(
'
$mode
.xcconfig'
);
}
/// The 'Podfile'.
/// The 'Podfile'.
File
get
podfile
=>
directory
.
childFile
(
'Podfile'
);
File
get
podfile
=>
directory
.
childFile
(
'Podfile'
);
...
@@ -198,23 +191,16 @@ class AndroidProject {
...
@@ -198,23 +191,16 @@ class AndroidProject {
AndroidProject
(
this
.
directory
);
AndroidProject
(
this
.
directory
);
File
get
gradleManifestFile
{
File
get
gradleManifestFile
{
return
_gradleManifestFile
??=
isUsingGradle
()
return
isUsingGradle
()
?
fs
.
file
(
fs
.
path
.
join
(
directory
.
path
,
'app'
,
'src'
,
'main'
,
'AndroidManifest.xml'
))
?
fs
.
file
(
fs
.
path
.
join
(
directory
.
path
,
'app'
,
'src'
,
'main'
,
'AndroidManifest.xml'
))
:
directory
.
childFile
(
'AndroidManifest.xml'
);
:
directory
.
childFile
(
'AndroidManifest.xml'
);
}
}
File
_gradleManifestFile
;
File
get
gradleAppOutV1File
{
File
get
gradleAppOutV1File
=>
gradleAppOutV1Directory
.
childFile
(
'app-debug.apk'
);
return
_gradleAppOutV1File
??=
gradleAppOutV1Directory
.
childFile
(
'app-debug.apk'
);
}
File
_gradleAppOutV1File
;
Directory
get
gradleAppOutV1Directory
{
Directory
get
gradleAppOutV1Directory
{
return
_gradleAppOutV1Directory
??=
fs
.
directory
(
fs
.
path
.
join
(
directory
.
path
,
'app'
,
'build'
,
'outputs'
,
'apk'
));
return
fs
.
directory
(
fs
.
path
.
join
(
directory
.
path
,
'app'
,
'build'
,
'outputs'
,
'apk'
));
}
}
Directory
_gradleAppOutV1Directory
;
bool
isUsingGradle
()
{
bool
isUsingGradle
()
{
return
directory
.
childFile
(
'build.gradle'
).
existsSync
();
return
directory
.
childFile
(
'build.gradle'
).
existsSync
();
...
@@ -233,8 +219,7 @@ class AndroidProject {
...
@@ -233,8 +219,7 @@ class AndroidProject {
}
}
}
}
/// Represents the contents of the .android-generated/ folder of a Flutter module
/// Represents the contents of the .android/ folder of a Flutter module project.
/// project.
class
AndroidModuleProject
{
class
AndroidModuleProject
{
AndroidModuleProject
(
this
.
directory
);
AndroidModuleProject
(
this
.
directory
);
...
@@ -243,9 +228,13 @@ class AndroidModuleProject {
...
@@ -243,9 +228,13 @@ class AndroidModuleProject {
Future
<
void
>
ensureReadyForPlatformSpecificTooling
(
FlutterProject
project
)
async
{
Future
<
void
>
ensureReadyForPlatformSpecificTooling
(
FlutterProject
project
)
async
{
if
(
_shouldRegenerate
())
{
if
(
_shouldRegenerate
())
{
final
Template
template
=
new
Template
.
fromName
(
fs
.
path
.
join
(
'module'
,
'android'
));
final
Template
template
=
new
Template
.
fromName
(
fs
.
path
.
join
(
'module'
,
'android'
));
template
.
render
(
directory
,
<
String
,
dynamic
>{
template
.
render
(
'androidIdentifier'
:
(
await
project
.
manifest
).
moduleDescriptor
[
'androidPackage'
],
directory
,
},
printStatusWhenWriting:
false
);
<
String
,
dynamic
>{
'androidIdentifier'
:
project
.
manifest
.
moduleDescriptor
[
'androidPackage'
],
},
printStatusWhenWriting:
false
,
);
gradle
.
injectGradleWrapper
(
directory
);
gradle
.
injectGradleWrapper
(
directory
);
}
}
await
gradle
.
updateLocalProperties
(
project:
project
,
requireAndroidSdk:
false
);
await
gradle
.
updateLocalProperties
(
project:
project
,
requireAndroidSdk:
false
);
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
b2800748
...
@@ -276,7 +276,7 @@ class FlutterDevice {
...
@@ -276,7 +276,7 @@ class FlutterDevice {
if
(
package
==
null
)
{
if
(
package
==
null
)
{
String
message
=
'No application found for
$targetPlatform
.'
;
String
message
=
'No application found for
$targetPlatform
.'
;
final
String
hint
=
getMissingPackageHintForPlatform
(
targetPlatform
);
final
String
hint
=
await
getMissingPackageHintForPlatform
(
targetPlatform
);
if
(
hint
!=
null
)
if
(
hint
!=
null
)
message
+=
'
\n
$hint
'
;
message
+=
'
\n
$hint
'
;
printError
(
message
);
printError
(
message
);
...
@@ -335,7 +335,7 @@ class FlutterDevice {
...
@@ -335,7 +335,7 @@ class FlutterDevice {
if
(
package
==
null
)
{
if
(
package
==
null
)
{
String
message
=
'No application found for
$targetPlatform
.'
;
String
message
=
'No application found for
$targetPlatform
.'
;
final
String
hint
=
getMissingPackageHintForPlatform
(
targetPlatform
);
final
String
hint
=
await
getMissingPackageHintForPlatform
(
targetPlatform
);
if
(
hint
!=
null
)
if
(
hint
!=
null
)
message
+=
'
\n
$hint
'
;
message
+=
'
\n
$hint
'
;
printError
(
message
);
printError
(
message
);
...
@@ -898,13 +898,13 @@ String findMainDartFile([String target]) {
...
@@ -898,13 +898,13 @@ String findMainDartFile([String target]) {
return
targetPath
;
return
targetPath
;
}
}
String
getMissingPackageHintForPlatform
(
TargetPlatform
platform
)
{
Future
<
String
>
getMissingPackageHintForPlatform
(
TargetPlatform
platform
)
async
{
switch
(
platform
)
{
switch
(
platform
)
{
case
TargetPlatform
.
android_arm
:
case
TargetPlatform
.
android_arm
:
case
TargetPlatform
.
android_arm64
:
case
TargetPlatform
.
android_arm64
:
case
TargetPlatform
.
android_x64
:
case
TargetPlatform
.
android_x64
:
case
TargetPlatform
.
android_x86
:
case
TargetPlatform
.
android_x86
:
final
FlutterProject
project
=
new
FlutterProject
(
fs
.
currentDirectory
);
final
FlutterProject
project
=
await
FlutterProject
.
current
(
);
final
String
manifestPath
=
fs
.
path
.
relative
(
project
.
android
.
gradleManifestFile
.
path
);
final
String
manifestPath
=
fs
.
path
.
relative
(
project
.
android
.
gradleManifestFile
.
path
);
return
'Is your project missing an
$manifestPath
?
\n
Consider running "flutter create ." to create one.'
;
return
'Is your project missing an
$manifestPath
?
\n
Consider running "flutter create ." to create one.'
;
case
TargetPlatform
.
ios
:
case
TargetPlatform
.
ios
:
...
...
packages/flutter_tools/lib/src/runner/flutter_command.dart
View file @
b2800748
...
@@ -332,7 +332,8 @@ abstract class FlutterCommand extends Command<Null> {
...
@@ -332,7 +332,8 @@ abstract class FlutterCommand extends Command<Null> {
if
(
shouldRunPub
)
{
if
(
shouldRunPub
)
{
await
pubGet
(
context:
PubContext
.
getVerifyContext
(
name
));
await
pubGet
(
context:
PubContext
.
getVerifyContext
(
name
));
await
new
FlutterProject
(
fs
.
currentDirectory
).
ensureReadyForPlatformSpecificTooling
();
final
FlutterProject
project
=
await
FlutterProject
.
current
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
}
}
setupApplicationPackages
();
setupApplicationPackages
();
...
...
packages/flutter_tools/test/android/gradle_test.dart
View file @
b2800748
...
@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/android/gradle.dart';
...
@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/android/gradle.dart';
import
'package:flutter_tools/src/artifacts.dart'
;
import
'package:flutter_tools/src/artifacts.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/flutter_manifest.dart'
;
import
'package:flutter_tools/src/flutter_manifest.dart'
;
import
'package:flutter_tools/src/ios/xcodeproj.dart'
;
import
'package:flutter_tools/src/ios/xcodeproj.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:flutter_tools/src/project.dart'
;
...
@@ -21,6 +22,7 @@ import '../src/common.dart';
...
@@ -21,6 +22,7 @@ import '../src/common.dart';
import
'../src/context.dart'
;
import
'../src/context.dart'
;
void
main
(
)
{
void
main
(
)
{
Cache
.
flutterRoot
=
getFlutterRoot
();
group
(
'gradle build'
,
()
{
group
(
'gradle build'
,
()
{
test
(
'do not crash if there is no Android SDK'
,
()
async
{
test
(
'do not crash if there is no Android SDK'
,
()
async
{
Exception
shouldBeToolExit
;
Exception
shouldBeToolExit
;
...
@@ -32,7 +34,7 @@ void main() {
...
@@ -32,7 +34,7 @@ void main() {
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
// will be null and our expectation would fail. That would remind us to make these tests
// will be null and our expectation would fail. That would remind us to make these tests
// hermetic before adding Android SDKs to the bots.
// hermetic before adding Android SDKs to the bots.
await
updateLocalProperties
(
project:
new
FlutterProject
(
fs
.
currentDirectory
));
await
updateLocalProperties
(
project:
await
FlutterProject
.
current
(
));
}
on
Exception
catch
(
e
)
{
}
on
Exception
catch
(
e
)
{
shouldBeToolExit
=
e
;
shouldBeToolExit
=
e
;
}
}
...
@@ -190,7 +192,7 @@ someOtherProperty: someOtherValue
...
@@ -190,7 +192,7 @@ someOtherProperty: someOtherValue
try
{
try
{
await
updateLocalProperties
(
await
updateLocalProperties
(
project:
new
FlutterProject
.
fromPath
(
'path/to/project'
),
project:
await
FlutterProject
.
fromPath
(
'path/to/project'
),
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
);
);
...
...
packages/flutter_tools/test/commands/create_test.dart
View file @
b2800748
...
@@ -344,8 +344,9 @@ void main() {
...
@@ -344,8 +344,9 @@ void main() {
);
);
projectDir
.
childDirectory
(
'ios'
).
deleteSync
(
recursive:
true
);
projectDir
.
childDirectory
(
'ios'
).
deleteSync
(
recursive:
true
);
await
_createProject
(
projectDir
,
<
String
>[
'--no-pub'
],
<
String
>[]);
await
_createProject
(
projectDir
,
<
String
>[
'--no-pub'
],
<
String
>[]);
final
FlutterProject
project
=
await
FlutterProject
.
fromDirectory
(
projectDir
);
expect
(
expect
(
await
new
FlutterProject
(
projectDir
)
.
ios
.
productBundleIdentifier
(),
await
project
.
ios
.
productBundleIdentifier
(),
'com.bar.foo.flutterProject'
,
'com.bar.foo.flutterProject'
,
);
);
},
timeout:
allowForCreateFlutterProject
);
},
timeout:
allowForCreateFlutterProject
);
...
@@ -370,8 +371,9 @@ void main() {
...
@@ -370,8 +371,9 @@ void main() {
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java'
,
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java'
,
],
],
);
);
final
FlutterProject
project
=
await
FlutterProject
.
fromDirectory
(
projectDir
);
expect
(
expect
(
await
new
FlutterProject
(
projectDir
)
.
example
.
ios
.
productBundleIdentifier
(),
await
project
.
example
.
ios
.
productBundleIdentifier
(),
'com.bar.foo.flutterProjectExample'
,
'com.bar.foo.flutterProjectExample'
,
);
);
},
timeout:
allowForCreateFlutterProject
);
},
timeout:
allowForCreateFlutterProject
);
...
...
packages/flutter_tools/test/ios/cocoapods_test.dart
View file @
b2800748
...
@@ -40,12 +40,12 @@ void main() {
...
@@ -40,12 +40,12 @@ void main() {
resultOfPodVersion
=
()
async
=>
exitsHappy
(
versionText
);
resultOfPodVersion
=
()
async
=>
exitsHappy
(
versionText
);
}
}
setUp
(()
{
setUp
(()
async
{
Cache
.
flutterRoot
=
'flutter'
;
Cache
.
flutterRoot
=
'flutter'
;
fs
=
new
MemoryFileSystem
();
fs
=
new
MemoryFileSystem
();
mockProcessManager
=
new
MockProcessManager
();
mockProcessManager
=
new
MockProcessManager
();
mockXcodeProjectInterpreter
=
new
MockXcodeProjectInterpreter
();
mockXcodeProjectInterpreter
=
new
MockXcodeProjectInterpreter
();
projectUnderTest
=
new
FlutterProject
(
fs
.
directory
(
'project'
));
projectUnderTest
=
await
FlutterProject
.
fromDirectory
(
fs
.
directory
(
'project'
));
projectUnderTest
.
ios
.
directory
.
createSync
(
recursive:
true
);
projectUnderTest
.
ios
.
directory
.
createSync
(
recursive:
true
);
cocoaPodsUnderTest
=
new
CocoaPods
();
cocoaPodsUnderTest
=
new
CocoaPods
();
pretendPodVersionIs
(
'1.5.0'
);
pretendPodVersionIs
(
'1.5.0'
);
...
@@ -138,7 +138,7 @@ void main() {
...
@@ -138,7 +138,7 @@ void main() {
'SWIFT_VERSION'
:
'4.0'
,
'SWIFT_VERSION'
:
'4.0'
,
});
});
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'project'
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
expect
(
projectUnderTest
.
ios
.
podfile
.
readAsStringSync
(),
'Swift podfile template'
);
expect
(
projectUnderTest
.
ios
.
podfile
.
readAsStringSync
(),
'Swift podfile template'
);
...
@@ -150,7 +150,7 @@ void main() {
...
@@ -150,7 +150,7 @@ void main() {
testUsingContext
(
'does not recreate Podfile when already present'
,
()
async
{
testUsingContext
(
'does not recreate Podfile when already present'
,
()
async
{
projectUnderTest
.
ios
.
podfile
..
createSync
()..
writeAsStringSync
(
'Existing Podfile'
);
projectUnderTest
.
ios
.
podfile
..
createSync
()..
writeAsStringSync
(
'Existing Podfile'
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'project'
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
expect
(
projectUnderTest
.
ios
.
podfile
.
readAsStringSync
(),
'Existing Podfile'
);
expect
(
projectUnderTest
.
ios
.
podfile
.
readAsStringSync
(),
'Existing Podfile'
);
...
@@ -161,7 +161,7 @@ void main() {
...
@@ -161,7 +161,7 @@ void main() {
testUsingContext
(
'does not create Podfile when we cannot interpret Xcode projects'
,
()
async
{
testUsingContext
(
'does not create Podfile when we cannot interpret Xcode projects'
,
()
async
{
when
(
mockXcodeProjectInterpreter
.
isInstalled
).
thenReturn
(
false
);
when
(
mockXcodeProjectInterpreter
.
isInstalled
).
thenReturn
(
false
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'project'
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
expect
(
projectUnderTest
.
ios
.
podfile
.
existsSync
(),
false
);
expect
(
projectUnderTest
.
ios
.
podfile
.
existsSync
(),
false
);
...
@@ -179,7 +179,7 @@ void main() {
...
@@ -179,7 +179,7 @@ void main() {
..
createSync
(
recursive:
true
)
..
createSync
(
recursive:
true
)
..
writeAsStringSync
(
'Existing release config'
);
..
writeAsStringSync
(
'Existing release config'
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'project'
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
cocoaPodsUnderTest
.
setupPodfile
(
project
.
ios
);
final
String
debugContents
=
projectUnderTest
.
ios
.
xcodeConfigFor
(
'Debug'
).
readAsStringSync
();
final
String
debugContents
=
projectUnderTest
.
ios
.
xcodeConfigFor
(
'Debug'
).
readAsStringSync
();
...
...
packages/flutter_tools/test/ios/xcodeproj_test.dart
View file @
b2800748
...
@@ -289,7 +289,7 @@ Information about project "Runner":
...
@@ -289,7 +289,7 @@ Information about project "Runner":
previewDart2:
true
,
previewDart2:
true
,
targetPlatform:
TargetPlatform
.
ios
,
targetPlatform:
TargetPlatform
.
ios
,
);
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'path/to/project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'path/to/project'
);
await
updateGeneratedXcodeProperties
(
await
updateGeneratedXcodeProperties
(
project:
project
,
project:
project
,
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
...
@@ -311,7 +311,7 @@ Information about project "Runner":
...
@@ -311,7 +311,7 @@ Information about project "Runner":
trackWidgetCreation:
true
,
trackWidgetCreation:
true
,
targetPlatform:
TargetPlatform
.
ios
,
targetPlatform:
TargetPlatform
.
ios
,
);
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'path/to/project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'path/to/project'
);
await
updateGeneratedXcodeProperties
(
await
updateGeneratedXcodeProperties
(
project:
project
,
project:
project
,
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
...
@@ -332,7 +332,7 @@ Information about project "Runner":
...
@@ -332,7 +332,7 @@ Information about project "Runner":
previewDart2:
true
,
previewDart2:
true
,
targetPlatform:
TargetPlatform
.
ios
,
targetPlatform:
TargetPlatform
.
ios
,
);
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'path/to/project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'path/to/project'
);
await
updateGeneratedXcodeProperties
(
await
updateGeneratedXcodeProperties
(
project:
project
,
project:
project
,
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
...
@@ -354,7 +354,7 @@ Information about project "Runner":
...
@@ -354,7 +354,7 @@ Information about project "Runner":
targetPlatform:
TargetPlatform
.
ios
,
targetPlatform:
TargetPlatform
.
ios
,
);
);
final
FlutterProject
project
=
new
FlutterProject
.
fromPath
(
'path/to/project'
);
final
FlutterProject
project
=
await
FlutterProject
.
fromPath
(
'path/to/project'
);
await
updateGeneratedXcodeProperties
(
await
updateGeneratedXcodeProperties
(
project:
project
,
project:
project
,
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
...
@@ -405,7 +405,7 @@ Information about project "Runner":
...
@@ -405,7 +405,7 @@ Information about project "Runner":
writeSchemaFile
(
fs
,
schemaData
);
writeSchemaFile
(
fs
,
schemaData
);
await
updateGeneratedXcodeProperties
(
await
updateGeneratedXcodeProperties
(
project:
new
FlutterProject
.
fromPath
(
'path/to/project'
),
project:
await
FlutterProject
.
fromPath
(
'path/to/project'
),
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
previewDart2:
false
,
previewDart2:
false
,
);
);
...
...
packages/flutter_tools/test/project_test.dart
View file @
b2800748
...
@@ -13,83 +13,83 @@ import 'src/context.dart';
...
@@ -13,83 +13,83 @@ import 'src/context.dart';
void
main
(
)
{
void
main
(
)
{
group
(
'Project'
,
()
{
group
(
'Project'
,
()
{
testInMemory
(
'knows location'
,
()
{
testInMemory
(
'knows location'
,
()
async
{
final
Directory
directory
=
fs
.
directory
(
'myproject'
);
final
Directory
directory
=
fs
.
directory
(
'myproject'
);
expect
(
expect
(
new
FlutterProject
(
directory
).
directory
.
absolute
.
path
,
(
await
FlutterProject
.
fromDirectory
(
directory
)
).
directory
.
absolute
.
path
,
directory
.
absolute
.
path
,
directory
.
absolute
.
path
,
);
);
expect
(
expect
(
new
FlutterProject
.
fromPath
(
directory
.
path
).
directory
.
absolute
.
path
,
(
await
FlutterProject
.
fromPath
(
directory
.
path
)
).
directory
.
absolute
.
path
,
directory
.
absolute
.
path
,
directory
.
absolute
.
path
,
);
);
});
});
group
(
'ensure ready for platform-specific tooling'
,
()
{
group
(
'ensure ready for platform-specific tooling'
,
()
{
testInMemory
(
'does nothing, if project is not created'
,
()
async
{
testInMemory
(
'does nothing, if project is not created'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
directory
.
existsSync
(),
isFalse
);
expect
(
project
.
directory
.
existsSync
(),
isFalse
);
});
});
testInMemory
(
'does nothing in plugin or package root project'
,
()
async
{
testInMemory
(
'does nothing in plugin or package root project'
,
()
async
{
final
FlutterProject
project
=
aPluginProject
();
final
FlutterProject
project
=
a
wait
a
PluginProject
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isFalse
);
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isFalse
);
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isFalse
);
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isFalse
);
});
});
testInMemory
(
'injects plugins'
,
()
async
{
testInMemory
(
'injects plugins'
,
()
async
{
final
FlutterProject
project
=
aProjectWithIos
();
final
FlutterProject
project
=
a
wait
a
ProjectWithIos
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isTrue
);
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isTrue
);
});
});
testInMemory
(
'generates Xcode configuration'
,
()
async
{
testInMemory
(
'generates Xcode configuration'
,
()
async
{
final
FlutterProject
project
=
aProjectWithIos
();
final
FlutterProject
project
=
a
wait
a
ProjectWithIos
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
await
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isTrue
);
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isTrue
);
});
});
});
});
group
(
'organization names set'
,
()
{
group
(
'organization names set'
,
()
{
testInMemory
(
'is empty, if project not created'
,
()
async
{
testInMemory
(
'is empty, if project not created'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
expect
(
await
project
.
organizationNames
(),
isEmpty
);
expect
(
await
project
.
organizationNames
(),
isEmpty
);
});
});
testInMemory
(
'is empty, if no platform folders exist'
,
()
async
{
testInMemory
(
'is empty, if no platform folders exist'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
project
.
directory
.
createSync
();
project
.
directory
.
createSync
();
expect
(
await
project
.
organizationNames
(),
isEmpty
);
expect
(
await
project
.
organizationNames
(),
isEmpty
);
});
});
testInMemory
(
'is populated from iOS bundle identifier'
,
()
async
{
testInMemory
(
'is populated from iOS bundle identifier'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
});
testInMemory
(
'is populated from Android application ID'
,
()
async
{
testInMemory
(
'is populated from Android application ID'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addAndroidWithApplicationId
(
project
.
directory
,
'io.flutter.someproject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
});
testInMemory
(
'is populated from iOS bundle identifier in plugin example'
,
()
async
{
testInMemory
(
'is populated from iOS bundle identifier in plugin example'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addIosWithBundleId
(
project
.
example
.
directory
,
'io.flutter.someProject'
);
addIosWithBundleId
(
project
.
example
.
directory
,
'io.flutter.someProject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
});
testInMemory
(
'is populated from Android application ID in plugin example'
,
()
async
{
testInMemory
(
'is populated from Android application ID in plugin example'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addAndroidWithApplicationId
(
project
.
example
.
directory
,
'io.flutter.someproject'
);
addAndroidWithApplicationId
(
project
.
example
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
});
testInMemory
(
'is populated from Android group in plugin'
,
()
async
{
testInMemory
(
'is populated from Android group in plugin'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addAndroidWithGroup
(
project
.
directory
,
'io.flutter.someproject'
);
addAndroidWithGroup
(
project
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
});
testInMemory
(
'is singleton, if sources agree'
,
()
async
{
testInMemory
(
'is singleton, if sources agree'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.flutter.someproject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.flutter.someproject'
);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
expect
(
await
project
.
organizationNames
(),
<
String
>[
'io.flutter'
]);
});
});
testInMemory
(
'is non-singleton, if sources disagree'
,
()
async
{
testInMemory
(
'is non-singleton, if sources disagree'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
await
someProject
();
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addIosWithBundleId
(
project
.
directory
,
'io.flutter.someProject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.clutter.someproject'
);
addAndroidWithApplicationId
(
project
.
directory
,
'io.clutter.someproject'
);
expect
(
expect
(
...
@@ -101,22 +101,22 @@ void main() {
...
@@ -101,22 +101,22 @@ void main() {
});
});
}
}
F
lutterProject
someProject
(
)
=>
new
FlutterProject
.
fromPath
(
'some_project'
);
F
uture
<
FlutterProject
>
someProject
()
=>
FlutterProject
.
fromPath
(
'some_project'
);
F
lutterProject
aProjectWithIos
(
)
{
F
uture
<
FlutterProject
>
aProjectWithIos
()
{
final
Directory
directory
=
fs
.
directory
(
'ios_project'
);
final
Directory
directory
=
fs
.
directory
(
'ios_project'
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
);
return
FlutterProject
.
fromDirectory
(
directory
);
}
}
F
lutterProject
aPluginProject
(
)
{
F
uture
<
FlutterProject
>
aPluginProject
()
{
final
Directory
directory
=
fs
.
directory
(
'plugin_project/example'
);
final
Directory
directory
=
fs
.
directory
(
'plugin_project/example'
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
.
parent
);
return
FlutterProject
.
fromDirectory
(
directory
.
parent
);
}
}
void
testInMemory
(
String
description
,
Future
<
Null
>
testMethod
())
{
void
testInMemory
(
String
description
,
Future
<
Null
>
testMethod
())
{
...
...
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