forbidden_imports_test.dart 11.7 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:file/file.dart';
6

7
import '../src/common.dart';
8
import 'test_utils.dart';
9

10
void main() {
11
  final String flutterTools = fileSystem.path.join(getFlutterRoot(), 'packages', 'flutter_tools');
12

13 14
  test('no imports of commands/* or test/* in lib/src/*', () {
    final List<String> skippedPaths = <String> [
15 16
      fileSystem.path.join(flutterTools, 'lib', 'src', 'commands'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'test'),
17
    ];
18
    bool isNotSkipped(FileSystemEntity entity) => skippedPaths.every((String path) => !entity.path.startsWith(path));
19

20
    final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, 'lib', 'src'))
21 22
      .listSync(recursive: true)
      .where(_isDartFile)
23
      .where(isNotSkipped)
24
      .map(_asFile);
25 26
    for (final File file in files) {
      for (final String line in file.readAsLinesSync()) {
27 28 29 30 31
        if (line.startsWith(RegExp(r'import.*package:'))) {
          continue;
        }
        if (line.startsWith(RegExp(r'import.*commands/'))
         || line.startsWith(RegExp(r'import.*test/'))) {
32
          final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
33 34 35 36 37 38 39
          fail('$relativePath imports $line. This import introduces a layering violation. '
               'Please find another way to access the information you are using.');
        }
      }
    }
  });

40 41
  test('no imports of globals without a global prefix', () {
    final List<String> skippedPaths = <String> [];
42
    bool isNotSkipped(FileSystemEntity entity) => skippedPaths.every((String path) => !entity.path.startsWith(path));
43

44
    final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, 'lib', 'src'))
45
      .listSync(recursive: true)
46
      .followedBy(fileSystem.directory(fileSystem.path.join(flutterTools, 'test',)).listSync(recursive: true))
47
      .where(_isDartFile)
48
      .where(isNotSkipped)
49
      .map(_asFile);
50 51
    for (final File file in files) {
      for (final String line in file.readAsLinesSync()) {
52 53 54
        if ((line.startsWith(RegExp(r'import.*globals.dart')) ||
                line.startsWith(RegExp(r'import.*globals_null_migrated.dart'))) &&
            !line.contains(r'as globals')) {
55
          final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
56
          fail('$relativePath imports globals_null_migrated.dart or globals.dart without a globals prefix.');
57 58 59 60 61
        }
      }
    }
  });

62
  test('no unauthorized imports of dart:io', () {
63
    final List<String> allowedPaths = <String>[
64 65
      // This is a standalone script invoked by xcode, not part of the tool
      fileSystem.path.join(flutterTools, 'bin', 'xcode_backend.dart'),
66 67 68
      fileSystem.path.join(flutterTools, 'lib', 'src', 'base', 'io.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'base', 'platform.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'base', 'error_handling_io.dart'),
69
      fileSystem.path.join(flutterTools, 'lib', 'src', 'base', 'multi_root_file_system.dart'),
70
    ];
71
    bool isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
72

73
    for (final String dirName in <String>['lib', 'bin']) {
74
      final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
75 76
        .listSync(recursive: true)
        .where(_isDartFile)
77
        .where(isNotAllowed)
78
        .map(_asFile);
79 80
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
81
          if (line.startsWith(RegExp(r'import.*dart:io')) &&
82
              !line.contains('flutter_ignore: dart_io_import')) {
83
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
84
            fail("$relativePath imports 'dart:io'; import 'lib/src/base/io.dart' instead");
85 86
          }
        }
87
      }
88 89 90
    }
  });

91 92 93
  test('no unauthorized imports of package:http', () {
    final List<String> allowedPaths = <String>[
      // Used only for multi-part file uploads, which are non-trivial to reimplement.
94
      fileSystem.path.join(flutterTools, 'lib', 'src', 'reporting', 'crash_reporting.dart'),
95
    ];
96
    bool isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
97 98 99 100 101

    for (final String dirName in <String>['lib', 'bin']) {
      final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
        .listSync(recursive: true)
        .where(_isDartFile)
102
        .where(isNotAllowed)
103 104 105 106
        .map(_asFile);
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
          if (line.startsWith(RegExp(r'import.*package:http/')) &&
107
              !line.contains('flutter_ignore: package_http_import')) {
108 109 110 111 112 113 114 115
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
            fail("$relativePath imports 'package:http'; import 'lib/src/base/io.dart' instead");
          }
        }
      }
    }
  });

116
  test('no unauthorized imports of test_api', () {
117
    final List<String> allowedPaths = <String>[
118 119
      fileSystem.path.join(flutterTools, 'lib', 'src', 'test', 'flutter_platform.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'test', 'flutter_web_platform.dart'),
120
      fileSystem.path.join(flutterTools, 'lib', 'src', 'test', 'test_wrapper.dart'),
121
    ];
122
    bool isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
123

124
    for (final String dirName in <String>['lib']) {
125
      final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
126 127
        .listSync(recursive: true)
        .where(_isDartFile)
128
        .where(isNotAllowed)
129
        .map(_asFile);
130 131
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
132
          if (line.startsWith(RegExp(r'import.*package:test_api')) &&
133
              !line.contains('flutter_ignore: test_api_import')) {
134
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
135 136 137 138 139 140 141
            fail("$relativePath imports 'package:test_api/test_api.dart';");
          }
        }
      }
    }
  });

142
  test('no unauthorized imports of package:path', () {
143
    final List<String> allowedPath = <String>[
144
      fileSystem.path.join(flutterTools, 'lib', 'src', 'isolated', 'web_compilation_delegate.dart'),
145
      fileSystem.path.join(flutterTools, 'test', 'general.shard', 'platform_plugins_test.dart'),
146
    ];
147
    for (final String dirName in <String>['lib', 'bin', 'test']) {
148
      final Iterable<File> files =  fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
149 150
        .listSync(recursive: true)
        .where(_isDartFile)
151
        .where((FileSystemEntity entity) => !allowedPath.contains(entity.path))
152
        .map(_asFile);
153 154
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
155
          if (line.startsWith(RegExp(r'import.*package:path/path.dart')) &&
156
              !line.contains('flutter_ignore: package_path_import')) {
157 158
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
            fail("$relativePath imports 'package:path/path.dart'; use 'fileSystem.path' instead");
159 160
          }
        }
161
      }
162 163
    }
  });
164

165
  test('no unauthorized imports of package:file/local.dart', () {
166
    final List<String> allowedPath = <String>[
167 168
      fileSystem.path.join(flutterTools, 'test', 'integration.shard', 'test_utils.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'base', 'file_system.dart'),
169 170
    ];
    for (final String dirName in <String>['lib', 'bin', 'test']) {
171
      final Iterable<File> files =  fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
172 173
        .listSync(recursive: true)
        .where(_isDartFile)
174
        .where((FileSystemEntity entity) => !allowedPath.contains(entity.path))
175 176 177 178
        .map(_asFile);
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
          if (line.startsWith(RegExp(r'import.*package:file/local.dart'))) {
179
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
180 181 182 183 184 185 186
            fail("$relativePath imports 'package:file/local.dart'; use 'lib/src/base/file_system.dart' instead");
          }
        }
      }
    }
  });

187
  test('no unauthorized imports of dart:convert', () {
188
    final List<String> allowedPaths = <String>[
189 190
      fileSystem.path.join(flutterTools, 'lib', 'src', 'convert.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'base', 'error_handling_io.dart'),
191
    ];
192
    bool isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
193

194
    for (final String dirName in <String>['lib']) {
195
      final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
196 197
        .listSync(recursive: true)
        .where(_isDartFile)
198
        .where(isNotAllowed)
199
        .map(_asFile);
200 201
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
202
          if (line.startsWith(RegExp(r'import.*dart:convert')) &&
203
              !line.contains('flutter_ignore: dart_convert_import')) {
204
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
205 206 207 208 209 210
            fail("$relativePath imports 'dart:convert'; import 'lib/src/convert.dart' instead");
          }
        }
      }
    }
  });
211

212
  test('no unauthorized imports of build_runner/dwds/devtools', () {
213
    final List<String> allowedPaths = <String>[
214 215
      fileSystem.path.join(flutterTools, 'test', 'src', 'isolated'),
      fileSystem.path.join(flutterTools, 'lib', 'src', 'isolated'),
216 217 218
      fileSystem.path.join(flutterTools, 'lib', 'executable.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'devfs_web.dart'),
      fileSystem.path.join(flutterTools, 'lib', 'resident_web_runner.dart'),
219
    ];
220
    bool isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => !entity.path.contains(path));
221

222
    for (final String dirName in <String>['lib']) {
223
      final Iterable<File> files = fileSystem.directory(fileSystem.path.join(flutterTools, dirName))
224 225
        .listSync(recursive: true)
        .where(_isDartFile)
226
        .where(isNotAllowed)
227
        .map(_asFile);
228 229
      for (final File file in files) {
        for (final String line in file.readAsLinesSync()) {
230 231 232
          if (line.startsWith(RegExp(r'import.*package:build_runner_core/build_runner_core.dart')) ||
              line.startsWith(RegExp(r'import.*package:build_runner/build_runner.dart')) ||
              line.startsWith(RegExp(r'import.*package:build_config/build_config.dart')) ||
233
              line.startsWith(RegExp(r'import.*dwds:*.dart')) ||
234
              line.startsWith(RegExp(r'import.*devtools_server:*.dart')) ||
235
              line.startsWith(RegExp(r'import.*build_runner/.*.dart'))) {
236
            final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
237
            fail('$relativePath imports a build_runner/dwds/devtools package');
238 239 240 241 242
          }
        }
      }
    }
  });
243 244

  test('no import of packages in tool_backend.dart', () {
245
    final File file = fileSystem.file(fileSystem.path.join(flutterTools, 'bin', 'tool_backend.dart'));
246 247
    for (final String line in file.readAsLinesSync()) {
      if (line.startsWith(RegExp(r'import.*package:.*'))) {
248
        final String relativePath = fileSystem.path.relative(file.path, from:flutterTools);
249 250 251 252
        fail('$relativePath imports a package');
      }
    }
  });
253
}
254

255
bool _isDartFile(FileSystemEntity entity) => entity is File && entity.path.endsWith('.dart');
256

257
File _asFile(FileSystemEntity entity) => entity as File;