blob: 10dd9a3b960a3afd2b7f6ff9dc73e2a3c2c455b1 [file] [log] [blame]
// Copyright (c) 2026, 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 'package:analysis_server_plugin/src/utilities/selection.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
extension SelectionExtension on Selection {
/// The end of the selection.
int get end => offset + length;
/// Returns the element of the constructor at the given [selection].
///
/// Returns `null` if
/// - the selection doesn't identify a constructor, or
/// - [mustHaveName] is `true` and the referenced constructor doesn't have a
/// name, or
/// - [mustNotHaveName] is `true` and the referenced constructor has a name.
ConstructorElement? constructor({
bool mustHaveName = false,
bool mustNotHaveName = false,
}) {
var node = coveringNode;
bool meetsRequirements(Object? name) {
if (name == null) {
if (mustHaveName) return false;
} else {
if (mustNotHaveName) return false;
}
return true;
}
if (node is ConstructorDeclaration) {
if (!meetsRequirements(node.name)) return null;
var left =
node.typeName?.offset ??
node.factoryKeyword?.offset ??
node.newKeyword?.offset ??
node.firstTokenAfterCommentAndMetadata.offset;
var right = node.separator?.offset ?? node.parameters.offset;
if (left <= offset && end <= right) {
return node.declaredFragment?.element;
}
} else if (node is SimpleIdentifier || node is FormalParameterList) {
var parent = node.parent;
if (parent is ConstructorDeclaration) {
if (!meetsRequirements(parent.name)) return null;
return parent.declaredFragment?.element;
} else if (parent is ConstructorName) {
if (!meetsRequirements(parent.name)) return null;
return parent.element;
}
} else if (node is PrimaryConstructorDeclaration) {
if (!meetsRequirements(node.constructorName)) return null;
return node.declaredFragment?.element;
} else if (node is PrimaryConstructorName) {
if (!meetsRequirements(node.name)) return null;
var parent = node.parent;
if (parent is PrimaryConstructorDeclaration) {
return parent.declaredFragment?.element;
}
} else if (node is NamedType) {
var parent = node.parent;
if (parent is ConstructorName) {
if (!meetsRequirements(node.name)) return null;
return parent.element;
}
} else if (node is ConstructorName) {
if (!meetsRequirements(node.name)) return null;
return node.element;
}
return null;
}
}