blob: 9a0a1a497f49d5226dac2fa05cd282bc208d08dc [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. 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:io';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
/// Wrapper class for some static utilities.
class GenUtil {
// Picks a top directory (command line, environment, or current).
static String getTop(String? top) {
if (top == null || top == '') {
top = Platform.environment['DART_TOP'];
}
if (top == null || top == '') {
top = Directory.current.path;
}
return top;
}
// Create an analyzer session.
static AnalysisSession createAnalysisSession([String? dart_top]) {
// Set paths. Note that for this particular use case, packageRoot can be
// any directory. Here, we set it to the top of the SDK development, and
// derive the required sdkPath from there.
final packageRoot = getTop(dart_top);
if (packageRoot == null) {
throw StateError('No environment variable DART_TOP');
}
final sdkPath = '$packageRoot/sdk';
// This does most of the hard work of getting the analyzer configured
// correctly. Typically the included paths are the files and directories
// that need to be analyzed, but the SDK is always available, so it isn't
// really important for this particular use case. We use the implementation
// class in order to pass in the sdkPath directly.
final provider = PhysicalResourceProvider.INSTANCE;
final collection = AnalysisContextCollectionImpl(
includedPaths: <String>[packageRoot],
excludedPaths: <String>[packageRoot + '/pkg/front_end/test'],
resourceProvider: provider,
sdkPath: sdkPath);
return collection.contexts[0].currentSession;
}
}
extension DartTypeExtension on DartType {
/// Returns an approximation of the [DartType] code, suitable for this tool.
String get asCode {
final type = this;
if (type is DynamicType) {
return 'dynamic';
} else if (type is FunctionType) {
final parameters = type.parameters.map((e) => e.type.asCode);
return type.returnType.asCode + ' Function($parameters)';
} else if (type is InterfaceType) {
final typeArguments = type.typeArguments;
if (typeArguments.isEmpty ||
typeArguments.every((t) => t is DynamicType)) {
return type.element2.name;
} else {
final typeArgumentsStr = typeArguments.map((t) => t.asCode).join(', ');
return '${type.element2.name}<$typeArgumentsStr>';
}
} else if (type is NeverType) {
return 'Never';
} else if (type is TypeParameterType) {
return type.element2.name;
} else if (type is VoidType) {
return 'void';
} else {
throw UnimplementedError('(${type.runtimeType}) $type');
}
}
}