blob: 81f8ceaac5a410716d04d42569b4d7f07f83de83 [file] [log] [blame]
// Copyright (c) 2018, 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/protocol/protocol_generated.dart'
show AnalysisGetSignatureResult;
import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/element_locator.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
/**
* A computer for the signature at the specified offset of a Dart [CompilationUnit].
*/
class DartUnitSignatureComputer {
final DartdocDirectiveInfo _dartdocInfo;
final AstNode _node;
DartUnitSignatureComputer(
this._dartdocInfo, CompilationUnit _unit, int _offset)
: _node = new NodeLocator(_offset).searchWithin(_unit);
bool get offsetIsValid => _node != null;
/**
* Returns the computed signature information, maybe `null`.
*/
AnalysisGetSignatureResult compute() {
if (_node == null) {
return null;
}
// Find the closest argument list.
var argsNode = _node;
while (argsNode != null && !(argsNode is ArgumentList)) {
// Certain nodes don't make sense to search above for an argument list
// (for example when inside a function epxression).
if (argsNode is FunctionExpression) {
return null;
}
argsNode = argsNode.parent;
}
if (argsNode == null) {
return null;
}
final args = argsNode;
String name;
ExecutableElement execElement;
if (args.parent is MethodInvocation) {
MethodInvocation method = args.parent;
name = method.methodName.name;
execElement = ElementLocator.locate(method) as ExecutableElement;
} else if (args.parent is InstanceCreationExpression) {
InstanceCreationExpression constructor = args.parent;
name = constructor.constructorName.type.name.name;
if (constructor.constructorName.name != null) {
name += ".${constructor.constructorName.name.name}";
}
execElement = ElementLocator.locate(constructor) as ExecutableElement;
}
if (execElement == null) {
return null;
}
final parameters =
execElement.parameters.map((p) => _convertParam(p)).toList();
return new AnalysisGetSignatureResult(name, parameters,
dartdoc: DartUnitHoverComputer.computeDocumentation(
_dartdocInfo, execElement));
}
ParameterInfo _convertParam(ParameterElement param) {
return new ParameterInfo(
param.isOptionalPositional
? ParameterKind.OPTIONAL
: param.isPositional ? ParameterKind.REQUIRED : ParameterKind.NAMED,
param.displayName,
param.type.displayName,
defaultValue: param.defaultValueCode);
}
}