[linting_tool] Add lint rules list (#856)

pull/857/head
Abdullah Deshmukh 3 years ago committed by GitHub
parent 3b65403631
commit 6bac1b9694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,8 @@
include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- lib/model/rule.g.dart
strong-mode:
implicit-casts: false
implicit-dynamic: false

@ -3,9 +3,11 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:linting_tool/model/rules_store.dart';
import 'package:linting_tool/theme/app_theme.dart';
import 'package:linting_tool/widgets/adaptive_nav.dart';
import 'package:linting_tool/routes.dart' as routes;
import 'package:provider/provider.dart';
class LintingTool extends StatefulWidget {
const LintingTool({Key? key}) : super(key: key);
@ -19,22 +21,25 @@ class LintingTool extends StatefulWidget {
class _LintingToolState extends State<LintingTool> {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Linting Tool',
theme: AppTheme.buildReplyLightTheme(context),
darkTheme: AppTheme.buildReplyDarkTheme(context),
themeMode: ThemeMode.light,
initialRoute: LintingTool.homeRoute,
onGenerateRoute: (settings) {
switch (settings.name) {
case LintingTool.homeRoute:
return MaterialPageRoute<void>(
builder: (context) => const AdaptiveNav(),
settings: settings,
);
}
return null;
},
return ChangeNotifierProvider<RuleStore>(
create: (context) => RuleStore(),
child: MaterialApp(
title: 'Flutter Linting Tool',
theme: AppTheme.buildReplyLightTheme(context),
darkTheme: AppTheme.buildReplyDarkTheme(context),
themeMode: ThemeMode.light,
initialRoute: LintingTool.homeRoute,
onGenerateRoute: (settings) {
switch (settings.name) {
case LintingTool.homeRoute:
return MaterialPageRoute<void>(
builder: (context) => const AdaptiveNav(),
settings: settings,
);
}
return null;
},
),
);
}
}

@ -0,0 +1,36 @@
// Copyright 2021 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'rule.g.dart';
@JsonSerializable()
class Rule extends Equatable {
final String name;
final String description;
final String group;
final String maturity;
final List<String> incompatible;
final List<String> sets;
final String details;
const Rule({
required this.name,
required this.description,
required this.group,
required this.maturity,
required this.incompatible,
required this.sets,
required this.details,
});
factory Rule.fromJson(Map<String, dynamic> json) => _$RuleFromJson(json);
Map<String, dynamic> toJson() => _$RuleToJson(this);
@override
List<Object?> get props => [name];
}

@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'rule.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Rule _$RuleFromJson(Map<String, dynamic> json) {
return Rule(
name: json['name'] as String,
description: json['description'] as String,
group: json['group'] as String,
maturity: json['maturity'] as String,
incompatible: (json['incompatible'] as List<dynamic>)
.map((e) => e as String)
.toList(),
sets: (json['sets'] as List<dynamic>).map((e) => e as String).toList(),
details: json['details'] as String,
);
}
Map<String, dynamic> _$RuleToJson(Rule instance) => <String, dynamic>{
'name': instance.name,
'description': instance.description,
'group': instance.group,
'maturity': instance.maturity,
'incompatible': instance.incompatible,
'sets': instance.sets,
'details': instance.details,
};

@ -0,0 +1,44 @@
// Copyright 2021 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:linting_tool/model/rule.dart';
import 'package:linting_tool/repository/repository.dart';
class RuleStore extends ChangeNotifier {
RuleStore() {
fetchRules();
}
bool _isLoading = true;
bool get isLoading => _isLoading;
List<Rule> _rules = [];
List<Rule> get rules => _rules;
String? _error;
String? get error => _error;
Future<void> fetchRules() async {
if (!_isLoading) _isLoading = true;
notifyListeners();
try {
var rules = await Repository().getRulesList();
_rules = rules;
} on SocketException catch (e) {
log(e.toString());
_error = 'Check internet connection.';
} on Exception catch (e) {
log(e.toString());
}
_isLoading = false;
notifyListeners();
}
}

@ -3,13 +3,70 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:linting_tool/model/rules_store.dart';
import 'package:linting_tool/layout/adaptive.dart';
import 'package:linting_tool/widgets/lint_expansion_tile.dart';
import 'package:provider/provider.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO(abd99): Implement HomePage, showing a list of supported lint rules.
return const Text('Home');
return Consumer<RuleStore>(
builder: (context, rulesStore, child) {
if (rulesStore.isLoading) {
return const CircularProgressIndicator.adaptive();
}
if (!rulesStore.isLoading) {
if (rulesStore.rules.isNotEmpty) {
final isDesktop = isDisplayLarge(context);
final isTablet = isDisplayMedium(context);
final startPadding = isTablet
? 60.0
: isDesktop
? 120.0
: 4.0;
final endPadding = isTablet
? 60.0
: isDesktop
? 120.0
: 4.0;
return ListView.separated(
padding: EdgeInsetsDirectional.only(
start: startPadding,
end: endPadding,
top: isDesktop ? 28 : 0,
bottom: isDesktop ? kToolbarHeight : 0,
),
itemCount: rulesStore.rules.length,
cacheExtent: 5,
itemBuilder: (context, index) {
return LintExpansionTile(
rule: rulesStore.rules[index],
);
},
separatorBuilder: (context, index) => const SizedBox(height: 4),
);
}
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(rulesStore.error ?? 'Failed to load rules.'),
const SizedBox(
height: 16.0,
),
IconButton(
onPressed: () => rulesStore.fetchRules(),
icon: const Icon(Icons.refresh),
),
],
);
},
);
}
}

@ -0,0 +1,26 @@
// Copyright 2021 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:linting_tool/model/rule.dart';
class APIProvider {
final _baseURL = 'https://dart-lang.github.io/linter';
Future<List<Rule>> getRulesList() async {
http.Response response =
await http.get(Uri.parse('$_baseURL//lints/machine/rules.json'));
if (response.statusCode == 200) {
List<Rule> rulesList = [];
final data = json.decode(response.body) as List;
for (var item in data) {
rulesList.add(Rule.fromJson(item as Map<String, dynamic>));
}
return rulesList;
} else {
throw Exception('Failed to load rules');
}
}
}

@ -0,0 +1,12 @@
// Copyright 2021 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:linting_tool/model/rule.dart';
import 'package:linting_tool/repository/api_provider.dart';
class Repository {
final _apiProvider = APIProvider();
Future<List<Rule>> getRulesList() => _apiProvider.getRulesList();
}

@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:linting_tool/theme/colors.dart';
@ -205,4 +206,22 @@ class AppTheme {
),
);
}
static MarkdownStyleSheet buildMarkDownTheme(ThemeData theme) {
final textTheme = theme.textTheme;
return MarkdownStyleSheet.largeFromTheme(theme).copyWith(
strong: textTheme.subtitle2!,
em: textTheme.bodyText2!.copyWith(
fontWeight: FontWeight.w900,
fontStyle: FontStyle.italic,
),
codeblockPadding: const EdgeInsets.all(8),
codeblockDecoration: BoxDecoration(
color: Colors.grey.shade100,
),
code: TextStyle(
backgroundColor: Colors.grey.shade100,
),
);
}
}

@ -0,0 +1,141 @@
// Copyright 2021 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:linting_tool/model/rule.dart';
import 'package:linting_tool/theme/app_theme.dart';
import 'package:linting_tool/theme/colors.dart';
class LintExpansionTile extends StatefulWidget {
final Rule rule;
const LintExpansionTile({
required this.rule,
Key? key,
}) : super(key: key);
@override
_LintExpansionTileState createState() => _LintExpansionTileState();
}
class _LintExpansionTileState extends State<LintExpansionTile> {
var isExpanded = false;
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var textTheme = theme.textTheme;
final rule = widget.rule;
final incompatibleString =
rule.incompatible.isNotEmpty ? rule.incompatible.join(', ') : 'none';
final setsString = rule.sets.isNotEmpty ? rule.sets.join(', ') : 'none';
return ExpansionTile(
collapsedBackgroundColor: AppColors.white50,
title: Text(
rule.name,
style: textTheme.subtitle1!.copyWith(
fontWeight: FontWeight.w700,
),
),
subtitle: Text(
rule.description,
style: textTheme.caption!,
),
initiallyExpanded: isExpanded,
onExpansionChanged: (value) {
setState(() {
isExpanded = value;
});
},
expandedAlignment: Alignment.centerLeft,
childrenPadding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
backgroundColor: AppColors.white50,
maintainState: true,
expandedCrossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(
children: [
TextSpan(
text: 'Group:',
style: textTheme.subtitle2,
),
TextSpan(
text: ' ${rule.group}',
),
],
),
textAlign: TextAlign.left,
),
Text.rich(
TextSpan(
children: [
TextSpan(
text: 'Maturity:',
style: textTheme.subtitle2,
),
TextSpan(
text: ' ${rule.maturity}',
),
],
),
textAlign: TextAlign.left,
),
Text.rich(
TextSpan(
children: [
TextSpan(
text: 'Incompatible:',
style: textTheme.subtitle2,
),
TextSpan(
text: ' $incompatibleString',
),
],
),
textAlign: TextAlign.left,
),
Text.rich(
TextSpan(
children: [
TextSpan(
text: 'Sets:',
style: textTheme.subtitle2,
),
TextSpan(
text: ' $setsString',
),
],
),
textAlign: TextAlign.left,
),
const SizedBox(
height: 16.0,
),
MarkdownBody(
data: rule.details,
selectable: true,
styleSheet: AppTheme.buildMarkDownTheme(theme),
),
const SizedBox(
height: 8.0,
),
Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
child: const Text('Add to profile'),
onPressed: () {
// TODO(abd99): Iplement adding to a profile.
},
),
),
const SizedBox(
height: 16.0,
),
],
);
}
}

@ -4,5 +4,9 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>

@ -1,6 +1,13 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "22.0.0"
adaptive_breakpoints:
dependency: "direct main"
description:
@ -8,6 +15,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.1"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
async:
dependency: transitive
description:
@ -22,6 +43,62 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
build:
dependency: transitive
description:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "7.0.1"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.1"
characters:
dependency: transitive
description:
@ -36,6 +113,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.3"
clock:
dependency: transitive
description:
@ -43,6 +134,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
collection:
dependency: transitive
description:
@ -50,6 +148,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
crypto:
dependency: transitive
description:
@ -64,6 +169,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
equatable:
dependency: "direct main"
description:
name: equatable
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
fake_async:
dependency: transitive
description:
@ -85,6 +204,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter:
dependency: "direct main"
description: flutter
@ -97,11 +223,32 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
flutter_markdown:
dependency: "direct main"
description:
name: flutter_markdown
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.2"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
glob:
dependency: transitive
description:
name: glob
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
google_fonts:
dependency: "direct main"
description:
@ -109,13 +256,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
http:
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.3"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
http_parser:
dependency: transitive
description:
@ -123,6 +284,34 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
io:
dependency: transitive
description:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
json_annotation:
dependency: "direct main"
description:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.4"
lints:
dependency: transitive
description:
@ -130,6 +319,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
markdown:
dependency: transitive
description:
name: markdown
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
matcher:
dependency: transitive
description:
@ -144,6 +347,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
path:
dependency: transitive
description:
@ -207,6 +431,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
pool:
dependency: transitive
description:
name: pool
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
process:
dependency: transitive
description:
@ -214,11 +445,53 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.1"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
source_span:
dependency: transitive
description:
@ -240,6 +513,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
stream_transform:
dependency: transitive
description:
name: stream_transform
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
string_scanner:
dependency: transitive
description:
@ -261,6 +541,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
typed_data:
dependency: transitive
description:
@ -275,6 +562,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
win32:
dependency: transitive
description:
@ -289,6 +590,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.13.0 <3.0.0"
flutter: ">=1.20.0"

@ -11,12 +11,19 @@ dependencies:
sdk: flutter
adaptive_breakpoints: ^0.0.4
cupertino_icons: ^1.0.2
equatable: ^2.0.3
flutter_markdown: ^0.6.2
google_fonts: ^2.1.0
http: ^0.13.3
json_annotation: ^4.0.1
provider: ^5.0.0
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.0.6
flutter_lints: ^1.0.3
json_serializable: ^4.1.4
flutter:
uses-material-design: true

Loading…
Cancel
Save