Skip to content

Commit

Permalink
Version 3.7.0-124.0.dev
Browse files Browse the repository at this point in the history
Merge cb5c73e into dev
  • Loading branch information
Dart CI committed Nov 8, 2024
2 parents ed9a5b1 + cb5c73e commit 239568d
Show file tree
Hide file tree
Showing 302 changed files with 39,503 additions and 21,977 deletions.
1 change: 0 additions & 1 deletion pkg/analysis_server/analyzer_use_new_elements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ lib/src/lsp/completion_utils.dart
lib/src/lsp/handlers/code_actions/dart.dart
lib/src/lsp/handlers/commands/abstract_refactor.dart
lib/src/lsp/handlers/custom/abstract_go_to.dart
lib/src/lsp/handlers/custom/handler_imports.dart
lib/src/lsp/handlers/handler_completion.dart
lib/src/lsp/handlers/handler_completion_resolve.dart
lib/src/lsp/handlers/handler_definition.dart
Expand Down
169 changes: 111 additions & 58 deletions pkg/analysis_server/lib/src/lsp/handlers/custom/handler_imports.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,98 +3,151 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/lsp_protocol/protocol.dart' hide Element;
import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/custom/abstract_go_to.dart';
import 'package:analysis_server/src/lsp/error_or.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/src/dart/ast/element_locator.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';

typedef _ImportRecord =
({ImportDirective directive, LibraryImportElement import});
typedef _ImportRecord = ({CompilationUnit unit, ImportDirective directive});

class ImportsHandler extends AbstractGoToHandler {
class ImportsHandler
extends SharedMessageHandler<TextDocumentPositionParams, List<Location>?> {
ImportsHandler(super.server);

@override
Method get handlesMessage => CustomMethods.imports;

@override
LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
TextDocumentPositionParams.jsonHandler;

@override
bool get requiresTrustedCaller => false;

/// Returns the import directives that import the given [element].
/// Although the base class supports returning a single element?, this
/// handler is documented to return a list of elements.
/// If no element is found, an empty list is returned.
/// Changing this to return a single element could be a breaking change for
/// clients.
@override
Either2<Location?, List<Location>> findRelatedLocations(
Element element,
Future<ErrorOr<List<Location>?>> handle(
TextDocumentPositionParams params,
MessageInfo message,
CancellationToken token,
) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
}

var pos = params.position;
var path = pathOfDoc(params.textDocument);
var library = await path.mapResult(requireResolvedLibrary);
var unit = (path, library).mapResultsSync<ResolvedUnitResult>((
path,
library,
) {
var unit = library.unitWithPath(path);
return unit != null
? success(unit)
: error(
ErrorCodes.InternalError,
'The library containing a path did not contain the path.',
);
});
var offset = unit.mapResultSync(
(unit) => toOffset(unit.unit.lineInfo, pos),
);

return (library, unit, offset).mapResults((library, unit, offset) async {
var node = NodeLocator(offset).searchWithin(unit.unit);
if (node == null) {
return success(null);
}

var element = ElementLocator.locate2(node);
if (element == null) {
return success(null);
}

String? prefix;
if (node is NamedType) {
prefix = node.importPrefix?.name.lexeme;
} else if (node.thisOrAncestorOfType<PrefixedIdentifier>()
case PrefixedIdentifier identifier) {
prefix = identifier.prefix.name;
} else if (node is SimpleIdentifier) {
if (node.parent case MethodInvocation(
target: SimpleIdentifier target?,
)) {
prefix = target.toString();
}
}

var enclosingElement = element.enclosingElement2;
if (enclosingElement is ExtensionElement2) {
element = enclosingElement;
}

var locations = _getImportLocations(element, library, unit, prefix);

return success(nullIfEmpty(locations));
});
}

/// Returns [Location]s for imports that import the given [element] into
/// [unit].
List<Location> _getImportLocations(
Element2 element,
ResolvedLibraryResult libraryResult,
ResolvedUnitResult unit,
String? prefix,
) {
var elementName = element.name;
var elementName = element.name3;
if (elementName == null) {
return Either2.t1(null);
return [];
}

var imports = _getImports(libraryResult);
var results = <Location>[];

var directives = <ImportDirective>[];
for (var (:directive, :import) in imports) {
Element? namespaceElement;
for (var (:unit, :directive) in imports) {
var import = directive.libraryImport;
if (import == null) continue;

if (prefix == null) {
namespaceElement = import.namespace.get(elementName);
} else {
namespaceElement = import.namespace.getPrefixed(prefix, elementName);
}
var importedElement =
prefix == null
? import.namespace.get2(elementName)
: import.namespace.getPrefixed2(prefix, elementName);

if (element is MultiplyDefinedElement) {
if (element.conflictingElements.contains(namespaceElement)) {
directives.add(directive);
}
} else if (namespaceElement == element) {
directives.add(directive);
var isMatch =
element is MultiplyDefinedElement2
? element.conflictingElements2.contains(importedElement)
: element == importedElement;

if (isMatch) {
var uri = uriConverter.toClientUri(
unit.declaredFragment!.source.fullName,
);
var lineInfo = unit.lineInfo;
var range = toRange(lineInfo, directive.offset, directive.length);
results.add(Location(uri: uri, range: range));
}
}
return Either2.t2(directives.map(_importToLocation).nonNulls.toList());

return results;
}

List<_ImportRecord> _getImports(ResolvedLibraryResult libraryResult) {
// TODO(dantup): Confirm that `units.first` is always the containing
// library.
var containingUnit = libraryResult.units.firstOrNull?.unit;
if (containingUnit == null) {
return const [];
}
var directives = containingUnit.directives.whereType<ImportDirective>();
var imports = <_ImportRecord>[];
for (var directive in directives) {
if (directive.element case var import?) {
imports.add((directive: directive, import: import));
}
}
return imports;
}

Location? _importToLocation(ImportDirective directive) {
var sourcePath = directive.element?.declaration.source?.fullName;
if (sourcePath == null) {
return null;
// TODO(dantup): With enhanced parts, we may need to look at more than
// just the first fragment.
var unit = libraryResult.units.first.unit;
for (var directive in unit.directives.whereType<ImportDirective>()) {
imports.add((unit: unit, directive: directive));
}

// TODO(FMorschel): Remove this when migrating to the new element model.
var locationLineInfo = server.getLineInfo(sourcePath);
if (locationLineInfo == null) {
return null;
}

return Location(
uri: uriConverter.toClientUri(sourcePath),
range: toRange(locationLineInfo, directive.offset, directive.length),
);
return imports;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2441,12 +2441,6 @@ LintCode.unrelated_type_equality_checks_in_expression:
status: needsEvaluation
LintCode.unrelated_type_equality_checks_in_pattern:
status: needsEvaluation
LintCode.unsafe_html_attribute:
status: noFix
LintCode.unsafe_html_method:
status: noFix
LintCode.unsafe_html_constructor:
status: noFix
LintCode.use_build_context_synchronously_async_use:
status: noFix
LintCode.use_build_context_synchronously_wrong_mounted:
Expand Down
72 changes: 65 additions & 7 deletions pkg/analyzer/lib/src/dart/element/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1913,28 +1913,89 @@ class DirectiveUriWithUnitImpl extends DirectiveUriWithRelativeUriImpl
}

/// The synthetic element representing the declaration of the type `dynamic`.
class DynamicElementImpl extends ElementImpl implements TypeDefiningElement {
/// Return the unique instance of this class.
static DynamicElementImpl get instance => DynamicTypeImpl.instance.element;
class DynamicElementImpl extends ElementImpl
implements TypeDefiningElement, TypeDefiningFragment {
/// The unique instance of this class.
static final DynamicElementImpl instance = DynamicElementImpl._();

/// Initialize a newly created instance of this class. Instances of this class
/// should <b>not</b> be created except as part of creating the type
/// associated with this element. The single instance of this class should be
/// accessed through the method [instance].
DynamicElementImpl() : super(Keyword.DYNAMIC.lexeme, -1) {
DynamicElementImpl._() : super(Keyword.DYNAMIC.lexeme, -1) {
setModifier(Modifier.SYNTHETIC, true);
}

@override
List<Element2> get children2 => const [];

@override
List<Fragment> get children3 => const [];

@override
DynamicElementImpl2 get element => DynamicElementImpl2.instance;

@override
Null get enclosingFragment => null;

@override
ElementKind get kind => ElementKind.DYNAMIC;

@override
Null get libraryFragment => null;

@override
String get name2 => 'dynamic';

@override
Null get nameOffset2 => null;

@override
Null get nextFragment => null;

@override
Null get previousFragment => null;

@override
T? accept<T>(ElementVisitor<T> visitor) => null;
}

/// The synthetic element representing the declaration of the type `dynamic`.
class DynamicElementImpl2 extends TypeDefiningElementImpl2 {
/// The unique instance of this class.
static final DynamicElementImpl2 instance = DynamicElementImpl2._();

DynamicElementImpl2._();

@override
Null get documentationComment => null;

@override
DynamicElementImpl get firstFragment => DynamicElementImpl.instance;

@override
bool get isSynthetic => true;

@override
ElementKind get kind => ElementKind.DYNAMIC;

@override
Null get library2 => null;

@override
Metadata get metadata2 {
return MetadataImpl(0, const [], () => null);
}

@override
String get name3 => 'dynamic';

@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return null;
}
}

/// A concrete implementation of an [ElementAnnotation].
class ElementAnnotationImpl implements ElementAnnotation {
/// The name of the top-level variable used to mark that a function always
Expand Down Expand Up @@ -8452,9 +8513,6 @@ class NeverElementImpl2 extends TypeDefiningElementImpl2 {

NeverElementImpl2._();

@override
List<Element2> get children2 => const [];

@override
Null get documentationComment => null;

Expand Down
11 changes: 4 additions & 7 deletions pkg/analyzer/lib/src/dart/element/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,14 @@ class DynamicTypeImpl extends TypeImpl
/// The unique instance of this class.
static final DynamicTypeImpl instance = DynamicTypeImpl._();

@override
final DynamicElementImpl element = DynamicElementImpl();

/// Prevent the creation of instances of this class.
DynamicTypeImpl._();

@override
Element2? get element3 => switch (element) {
Fragment(:var element) => element,
_ => null,
};
DynamicElementImpl get element => DynamicElementImpl.instance;

@override
DynamicElementImpl2 get element3 => DynamicElementImpl2.instance;

@override
int get hashCode => 1;
Expand Down
10 changes: 5 additions & 5 deletions pkg/analyzer/lib/src/utilities/extensions/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ extension Element2OrNullExtension on Element2? {
Element? get asElement {
var self = this;
switch (self) {
case DynamicElementImpl():
return self;
case DynamicElementImpl2():
return DynamicElementImpl.instance;
case GetterElement():
return self.firstFragment as Element;
case MultiplyDefinedElementImpl2 element2:
return element2.asElement;
case NeverElementImpl():
return self;
case NeverElementImpl2():
return NeverElementImpl.instance;
case PrefixElementImpl():
return self;
case TopLevelFunctionElementImpl():
Expand Down Expand Up @@ -135,7 +135,7 @@ extension ElementOrNullExtension on Element? {
if (self == null) {
return null;
} else if (self is DynamicElementImpl) {
return self;
return DynamicElementImpl2.instance;
} else if (self is FunctionElementImpl) {
return self.element;
} else if (self is InterfaceElementImpl) {
Expand Down
Loading

0 comments on commit 239568d

Please sign in to comment.