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
7bff366b
Unverified
Commit
7bff366b
authored
Apr 30, 2021
by
Greg Spencer
Committed by
GitHub
Apr 30, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert snippets tool to null safety (#78646)
parent
bd4f8c4b
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
72 additions
and
65 deletions
+72
-65
analyze_sample_code.dart
dev/bots/analyze_sample_code.dart
+4
-1
configuration.dart
dev/snippets/lib/configuration.dart
+7
-5
main.dart
dev/snippets/lib/main.dart
+15
-17
snippets.dart
dev/snippets/lib/snippets.dart
+40
-36
pubspec.yaml
dev/snippets/pubspec.yaml
+1
-1
configuration_test.dart
dev/snippets/test/configuration_test.dart
+1
-1
snippets_test.dart
dev/snippets/test/snippets_test.dart
+4
-4
No files found.
dev/bots/analyze_sample_code.dart
View file @
7bff366b
...
...
@@ -355,7 +355,10 @@ class SampleChecker {
}
else
{
return
Process
.
runSync
(
_dartExecutable
,
<
String
>[
path
.
canonicalize
(
_snippetsSnapshotPath
!),
...
args
],
<
String
>[
path
.
canonicalize
(
_snippetsSnapshotPath
!),
...
args
,
],
workingDirectory:
workingDirectory
,
);
}
...
...
dev/snippets/lib/configuration.dart
View file @
7bff366b
...
...
@@ -27,7 +27,7 @@ String getEnumName(dynamic enumItem) {
/// A class to compute the configuration of the snippets input and output
/// locations based in the current location of the snippets main.dart.
class
Configuration
{
Configuration
({
@
required
this
.
flutterRoot
})
:
assert
(
flutterRoot
!=
null
);
Configuration
({
required
this
.
flutterRoot
})
:
assert
(
flutterRoot
!=
null
);
final
Directory
flutterRoot
;
...
...
@@ -37,20 +37,22 @@ class Configuration {
Directory
get
configDirectory
{
_configPath
??=
Directory
(
path
.
canonicalize
(
path
.
join
(
flutterRoot
.
absolute
.
path
,
'dev'
,
'snippets'
,
'config'
)));
return
_configPath
;
return
_configPath
!
;
}
Directory
_configPath
;
// Nullable so that we can use it as a lazy cache.
Directory
?
_configPath
;
/// This is where the snippets themselves will be written, in order to be
/// uploaded to the docs site.
Directory
get
outputDirectory
{
_docsDirectory
??=
Directory
(
path
.
canonicalize
(
path
.
join
(
flutterRoot
.
absolute
.
path
,
'dev'
,
'docs'
,
'doc'
,
'snippets'
)));
return
_docsDirectory
;
return
_docsDirectory
!
;
}
Directory
_docsDirectory
;
// Nullable so that we can use it as a lazy cache.
Directory
?
_docsDirectory
;
/// This makes sure that the output directory exists.
void
createOutputDirectory
()
{
...
...
dev/snippets/lib/main.dart
View file @
7bff366b
...
...
@@ -22,13 +22,13 @@ const String _kTypeOption = 'type';
const
String
_kShowDartPad
=
'dartpad'
;
String
getChannelName
(
)
{
final
RegExp
gitBranchRegexp
=
RegExp
(
r'^## (.*)'
);
final
RegExp
gitBranchRegexp
=
RegExp
(
r'^## (
?<branch>
.*)'
);
final
ProcessResult
gitResult
=
Process
.
runSync
(
'git'
,
<
String
>[
'status'
,
'-b'
,
'--porcelain'
]);
if
(
gitResult
.
exitCode
!=
0
)
throw
'git status exit with non-zero exit code:
${gitResult.exitCode}
'
;
final
Match
gitBranchMatch
=
gitBranchRegexp
.
firstMatch
(
final
RegExpMatch
?
gitBranchMatch
=
gitBranchRegexp
.
firstMatch
(
(
gitResult
.
stdout
as
String
).
trim
().
split
(
'
\n
'
).
first
);
return
gitBranchMatch
==
null
?
'<unknown>'
:
gitBranchMatch
.
group
(
1
)
.
split
(
'...'
).
first
;
return
gitBranchMatch
==
null
?
'<unknown>'
:
gitBranchMatch
.
namedGroup
(
'branch'
)!
.
split
(
'...'
).
first
;
}
/// Generates snippet dartdoc output for a given input, and creates any sample
...
...
@@ -113,8 +113,7 @@ void main(List<String> argList) {
}
final
SnippetType
snippetType
=
SnippetType
.
values
.
firstWhere
((
SnippetType
type
)
=>
getEnumName
(
type
)
==
args
[
_kTypeOption
],
orElse:
()
=>
null
);
assert
(
snippetType
!=
null
,
"Unable to find '
${args[_kTypeOption]}
' in SnippetType enum."
);
.
firstWhere
((
SnippetType
type
)
=>
getEnumName
(
type
)
==
args
[
_kTypeOption
]);
if
(
args
[
_kShowDartPad
]
==
true
&&
snippetType
!=
SnippetType
.
sample
)
{
errorExit
(
'
${args[_kTypeOption]}
was selected, but the --dartpad flag is only valid '
...
...
@@ -132,7 +131,7 @@ void main(List<String> argList) {
errorExit
(
'The input file
${input.path}
does not exist.'
);
}
String
template
;
String
?
template
;
if
(
snippetType
==
SnippetType
.
sample
)
{
final
String
templateArg
=
args
[
_kTemplateOption
]
as
String
;
if
(
templateArg
==
null
||
templateArg
.
isEmpty
)
{
...
...
@@ -143,25 +142,24 @@ void main(List<String> argList) {
template
=
templateArg
.
replaceAll
(
RegExp
(
r'.tmpl$'
),
''
);
}
String
emptyToNull
(
String
value
)
=>
value
?.
isEmpty
??
true
?
null
:
value
;
final
String
packageName
=
emptyToNull
(
args
[
_kPackageOption
]
as
String
);
final
String
libraryName
=
emptyToNull
(
args
[
_kLibraryOption
]
as
String
);
final
String
elementName
=
emptyToNull
(
args
[
_kElementOption
]
as
String
);
final
String
serial
=
emptyToNull
(
args
[
_kSerialOption
]
as
String
);
final
String
packageName
=
args
[
_kPackageOption
]
as
String
?
??
''
;
final
String
libraryName
=
args
[
_kLibraryOption
]
as
String
?
??
''
;
final
String
elementName
=
args
[
_kElementOption
]
as
String
?
??
''
;
final
String
serial
=
args
[
_kSerialOption
]
as
String
?
??
''
;
final
List
<
String
>
id
=
<
String
>[];
if
(
args
[
_kOutputOption
]
!=
null
)
{
id
.
add
(
path
.
basename
(
path
.
basenameWithoutExtension
(
args
[
_kOutputOption
]
as
String
)));
}
else
{
if
(
packageName
!=
null
&&
packageName
!=
'flutter'
)
{
if
(
packageName
.
isNotEmpty
&&
packageName
!=
'flutter'
)
{
id
.
add
(
packageName
);
}
if
(
libraryName
!=
null
)
{
if
(
libraryName
.
isNotEmpty
)
{
id
.
add
(
libraryName
);
}
if
(
elementName
!=
null
)
{
if
(
elementName
.
isNotEmpty
)
{
id
.
add
(
elementName
);
}
if
(
serial
!=
null
)
{
if
(
serial
.
isNotEmpty
)
{
id
.
add
(
serial
);
}
if
(
id
.
isEmpty
)
{
...
...
@@ -178,10 +176,10 @@ void main(List<String> argList) {
showDartPad:
args
[
_kShowDartPad
]
as
bool
,
template:
template
,
output:
args
[
_kOutputOption
]
!=
null
?
File
(
args
[
_kOutputOption
]
as
String
)
:
null
,
metadata:
<
String
,
Object
>{
metadata:
<
String
,
Object
?
>{
'sourcePath'
:
environment
[
'SOURCE_PATH'
],
'sourceLine'
:
environment
[
'SOURCE_LINE'
]
!=
null
?
int
.
tryParse
(
environment
[
'SOURCE_LINE'
])
?
int
.
tryParse
(
environment
[
'SOURCE_LINE'
]
!
)
:
null
,
'id'
:
id
.
join
(
'.'
),
'channel'
:
getChannelName
(),
...
...
dev/snippets/lib/snippets.dart
View file @
7bff366b
...
...
@@ -6,7 +6,6 @@ import 'dart:convert';
import
'dart:io'
;
import
'package:dart_style/dart_style.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'configuration.dart'
;
...
...
@@ -19,7 +18,7 @@ void errorExit(String message) {
// A Tuple containing the name and contents associated with a code block in a
// snippet.
class
_ComponentTuple
{
_ComponentTuple
(
this
.
name
,
this
.
contents
,
{
String
language
})
:
language
=
language
??
''
;
_ComponentTuple
(
this
.
name
,
this
.
contents
,
{
this
.
language
=
''
})
;
final
String
name
;
final
List
<
String
>
contents
;
final
String
language
;
...
...
@@ -29,7 +28,7 @@ class _ComponentTuple {
/// Generates the snippet HTML, as well as saving the output snippet main to
/// the output directory.
class
SnippetGenerator
{
SnippetGenerator
({
Configuration
configuration
})
SnippetGenerator
({
Configuration
?
configuration
})
:
configuration
=
configuration
??
// Flutter's root is four directories up from this script.
Configuration
(
flutterRoot:
Directory
(
Platform
.
environment
[
'FLUTTER_ROOT'
]
...
...
@@ -52,7 +51,7 @@ class SnippetGenerator {
File
getOutputFile
(
String
id
)
=>
File
(
path
.
join
(
configuration
.
outputDirectory
.
path
,
'
$id
.dart'
));
/// Gets the path to the template file requested.
File
getTemplatePath
(
String
templateName
,
{
Directory
templatesDir
})
{
File
?
getTemplatePath
(
String
templateName
,
{
Directory
?
templatesDir
})
{
final
Directory
templateDir
=
templatesDir
??
configuration
.
templatesDirectory
;
final
File
templateFile
=
File
(
path
.
join
(
templateDir
.
path
,
'
$templateName
.tmpl'
));
return
templateFile
.
existsSync
()
?
templateFile
:
null
;
...
...
@@ -61,7 +60,7 @@ class SnippetGenerator {
/// Injects the [injections] into the [template], and turning the
/// "description" injection into a comment. Only used for
/// [SnippetType.sample] snippets.
String
interpolateTemplate
(
List
<
_ComponentTuple
>
injections
,
String
template
,
Map
<
String
,
Object
>
metadata
)
{
String
interpolateTemplate
(
List
<
_ComponentTuple
>
injections
,
String
template
,
Map
<
String
,
Object
?
>
metadata
)
{
final
RegExp
moustacheRegExp
=
RegExp
(
'{{([^}]+)}}'
);
return
template
.
replaceAllMapped
(
moustacheRegExp
,
(
Match
match
)
{
if
(
match
[
1
]
==
'description'
)
{
...
...
@@ -86,9 +85,12 @@ class SnippetGenerator {
// mustache reference, since we want to allow the sections to be
// "optional" in the input: users shouldn't be forced to add an empty
// "```dart preamble" section if that section would be empty.
final
_ComponentTuple
result
=
injections
.
firstWhere
((
_ComponentTuple
tuple
)
=>
tuple
.
name
==
match
[
1
],
orElse:
()
=>
null
);
return
result
?.
mergedContent
??
(
metadata
[
match
[
1
]]
??
''
).
toString
();
final
int
componentIndex
=
injections
.
indexWhere
((
_ComponentTuple
tuple
)
=>
tuple
.
name
==
match
[
1
]);
if
(
componentIndex
==
-
1
)
{
return
(
metadata
[
match
[
1
]]
??
''
).
toString
();
}
return
injections
[
componentIndex
].
mergedContent
;
}
}).
trim
();
}
...
...
@@ -100,10 +102,15 @@ class SnippetGenerator {
///
/// Takes into account the [type] and doesn't substitute in the id and the app
/// if not a [SnippetType.sample] snippet.
String
interpolateSkeleton
(
SnippetType
type
,
List
<
_ComponentTuple
>
injections
,
String
skeleton
,
Map
<
String
,
Object
>
metadata
)
{
String
interpolateSkeleton
(
SnippetType
type
,
List
<
_ComponentTuple
>
injections
,
String
skeleton
,
Map
<
String
,
Object
?>
metadata
,
)
{
final
List
<
String
>
result
=
<
String
>[];
const
HtmlEscape
htmlEscape
=
HtmlEscape
();
String
language
;
String
language
=
'dart'
;
for
(
final
_ComponentTuple
injection
in
injections
)
{
if
(!
injection
.
name
.
startsWith
(
'code'
))
{
continue
;
...
...
@@ -133,11 +140,11 @@ class SnippetGenerator {
final
Map
<
String
,
String
>
substitutions
=
<
String
,
String
>{
'description'
:
description
,
'code'
:
htmlEscape
.
convert
(
result
.
join
(
'
\n
'
)),
'language'
:
language
??
'dart'
,
'language'
:
language
,
'serial'
:
''
,
'id'
:
metadata
[
'id'
]
as
String
,
'id'
:
metadata
[
'id'
]
!
as
String
,
'channel'
:
channel
,
'element'
:
metadata
[
'element'
]
as
String
??
''
,
'element'
:
(
metadata
[
'element'
]
??
''
)
as
String
,
'app'
:
''
,
};
if
(
type
==
SnippetType
.
sample
)
{
...
...
@@ -146,7 +153,7 @@ class SnippetGenerator {
..[
'app'
]
=
htmlEscape
.
convert
(
injections
.
firstWhere
((
_ComponentTuple
tuple
)
=>
tuple
.
name
==
'app'
).
mergedContent
);
}
return
skeleton
.
replaceAllMapped
(
RegExp
(
'{{(
${substitutions.keys.join('|')}
)}}'
),
(
Match
match
)
{
return
substitutions
[
match
[
1
]];
return
substitutions
[
match
[
1
]]
??
''
;
});
}
...
...
@@ -157,16 +164,16 @@ class SnippetGenerator {
input
=
input
.
trim
();
final
List
<
String
>
description
=
<
String
>[];
final
List
<
_ComponentTuple
>
components
=
<
_ComponentTuple
>[];
String
language
;
final
RegExp
codeStartEnd
=
RegExp
(
r'^\s*```(
[-\w]+|[-\w]+ (
[-\w]+))?\s*$'
);
String
?
language
;
final
RegExp
codeStartEnd
=
RegExp
(
r'^\s*```(
?<language>[-\w]+|[-\w]+ (?<section>
[-\w]+))?\s*$'
);
for
(
final
String
line
in
input
.
split
(
'
\n
'
))
{
final
Match
match
=
codeStartEnd
.
firstMatch
(
line
);
final
RegExpMatch
?
match
=
codeStartEnd
.
firstMatch
(
line
);
if
(
match
!=
null
)
{
// If we saw the start or end of a code block
inCodeBlock
=
!
inCodeBlock
;
if
(
match
[
1
]
!=
null
)
{
language
=
match
[
1
];
if
(
match
[
2
]
!=
null
)
{
components
.
add
(
_ComponentTuple
(
'code-
${match
[2]
}
'
,
<
String
>[],
language:
language
));
if
(
match
.
namedGroup
(
'language'
)
!=
null
)
{
language
=
match
[
1
]
!
;
if
(
match
.
namedGroup
(
'section'
)
!=
null
)
{
components
.
add
(
_ComponentTuple
(
'code-
${match
.namedGroup('section')
}
'
,
<
String
>[],
language:
language
));
}
else
{
components
.
add
(
_ComponentTuple
(
'code'
,
<
String
>[],
language:
language
));
}
...
...
@@ -191,7 +198,7 @@ class SnippetGenerator {
}
String
_loadFileAsUtf8
(
File
file
)
{
return
file
.
readAsStringSync
(
encoding:
Encoding
.
getByName
(
'utf-8'
)
);
return
file
.
readAsStringSync
(
encoding:
utf8
);
}
String
_addLineNumbers
(
String
app
)
{
...
...
@@ -228,13 +235,12 @@ class SnippetGenerator {
File
input
,
SnippetType
type
,
{
bool
showDartPad
=
false
,
String
template
,
File
output
,
@required
Map
<
String
,
Object
>
metadata
,
String
?
template
,
File
?
output
,
required
Map
<
String
,
Object
?
>
metadata
,
})
{
assert
(
template
!=
null
||
type
!=
SnippetType
.
sample
);
assert
(
metadata
!=
null
&&
metadata
[
'id'
]
!=
null
);
assert
(
input
!=
null
);
assert
(
metadata
[
'id'
]
!=
null
);
assert
(!
showDartPad
||
type
==
SnippetType
.
sample
,
'Only application samples work with dartpad.'
);
final
List
<
_ComponentTuple
>
snippetData
=
parseInput
(
_loadFileAsUtf8
(
input
));
switch
(
type
)
{
...
...
@@ -244,10 +250,9 @@ class SnippetGenerator {
stderr
.
writeln
(
'Unable to find the templates directory.'
);
exit
(
1
);
}
final
File
templateFile
=
getTemplatePath
(
template
,
templatesDir:
templatesDir
);
final
File
?
templateFile
=
getTemplatePath
(
template
!
,
templatesDir:
templatesDir
);
if
(
templateFile
==
null
)
{
stderr
.
writeln
(
'The template
$template
was not found in the templates directory
${templatesDir.path}
'
);
stderr
.
writeln
(
'The template
$template
was not found in the templates directory
${templatesDir.path}
'
);
exit
(
1
);
}
final
String
templateContents
=
_loadFileAsUtf8
(
templateFile
);
...
...
@@ -261,20 +266,19 @@ class SnippetGenerator {
}
snippetData
.
add
(
_ComponentTuple
(
'app'
,
app
.
split
(
'
\n
'
)));
final
File
outputFile
=
output
??
getOutputFile
(
metadata
[
'id'
]
as
String
);
final
File
outputFile
=
output
??
getOutputFile
(
metadata
[
'id'
]
!
as
String
);
stderr
.
writeln
(
'Writing to
${outputFile.absolute.path}
'
);
outputFile
.
writeAsStringSync
(
app
);
final
File
metadataFile
=
File
(
path
.
join
(
path
.
dirname
(
outputFile
.
path
),
'
${path.basenameWithoutExtension(outputFile.path)}
.json'
));
stderr
.
writeln
(
'Writing metadata to
${metadataFile.absolute.path}
'
);
final
_ComponentTuple
description
=
snippetData
.
firstWhere
(
(
_ComponentTuple
data
)
=>
data
.
name
==
'description'
,
orElse:
()
=>
null
,
);
final
int
descriptionIndex
=
snippetData
.
indexWhere
(
(
_ComponentTuple
data
)
=>
data
.
name
==
'description'
);
final
String
descriptionString
=
descriptionIndex
==
-
1
?
''
:
snippetData
[
descriptionIndex
].
mergedContent
;
metadata
.
addAll
(<
String
,
Object
>{
'file'
:
path
.
basename
(
outputFile
.
path
),
'description'
:
description
?.
mergedContent
,
'description'
:
description
String
,
});
metadataFile
.
writeAsStringSync
(
jsonEncoder
.
convert
(
metadata
));
break
;
...
...
dev/snippets/pubspec.yaml
View file @
7bff366b
...
...
@@ -5,7 +5,7 @@ description: A code snippet dartdoc extension for Flutter API docs.
homepage
:
https://github.com/flutter/flutter
environment
:
sdk
:
"
>=2.
2.2
<3.0.0"
sdk
:
"
>=2.
12.1
<3.0.0"
dartdoc
:
# Exclude this package from the hosted API docs (Ironically...).
...
...
dev/snippets/test/configuration_test.dart
View file @
7bff366b
...
...
@@ -9,7 +9,7 @@ import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
void
main
(
)
{
group
(
'Configuration'
,
()
{
Configuration
config
;
late
Configuration
config
;
setUp
(()
{
config
=
Configuration
(
flutterRoot:
Directory
(
'/flutter sdk'
));
...
...
dev/snippets/test/snippets_test.dart
View file @
7bff366b
...
...
@@ -12,10 +12,10 @@ import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
void
main
(
)
{
group
(
'Generator'
,
()
{
Configuration
configuration
;
SnippetGenerator
generator
;
Directory
tmpDir
;
File
template
;
late
Configuration
configuration
;
late
SnippetGenerator
generator
;
late
Directory
tmpDir
;
late
File
template
;
setUp
(()
{
tmpDir
=
Directory
.
systemTemp
.
createTempSync
(
'flutter_snippets_test.'
);
...
...
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