blob: bbcf5ac901951050691a80c5da7b4d9f90ac375f [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 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/services/available_declarations.dart';
import 'package:analyzer/src/services/available_declarations.dart' as ad;
class Declaration {
final int fileIndex;
final LineInfo lineInfo;
final String name;
final DeclarationKind kind;
final int offset;
final int line;
final int column;
final int codeOffset;
final int codeLength;
final String? className;
final String? mixinName;
final String? parameters;
Declaration(
this.fileIndex,
this.lineInfo,
this.name,
this.kind,
this.offset,
this.line,
this.column,
this.codeOffset,
this.codeLength,
this.className,
this.mixinName,
this.parameters,
);
}
enum DeclarationKind {
CLASS,
CLASS_TYPE_ALIAS,
CONSTRUCTOR,
ENUM,
ENUM_CONSTANT,
EXTENSION,
FIELD,
FUNCTION,
FUNCTION_TYPE_ALIAS,
GETTER,
METHOD,
MIXIN,
SETTER,
TYPE_ALIAS,
VARIABLE
}
class WorkspaceSymbols {
final DeclarationsTracker tracker;
WorkspaceSymbols(this.tracker);
List<Declaration> declarations(
RegExp? regExp, int? maxResults, Set<String> files,
{String? onlyForFile}) {
_doTrackerWork();
var declarations = <Declaration>[];
var pathToIndex = <String, int>{};
int getPathIndex(String path) {
var index = pathToIndex[path];
if (index == null) {
index = files.length;
files.add(path);
pathToIndex[path] = index;
}
return index;
}
if (maxResults != null && declarations.length >= maxResults) {
throw const _MaxNumberOfDeclarationsError();
}
void addDeclaration(ad.Declaration declaration) {
if (maxResults != null && declarations.length >= maxResults) {
throw const _MaxNumberOfDeclarationsError();
}
var path = declaration.locationPath;
if (onlyForFile != null && path != onlyForFile) {
return;
}
declaration.children.forEach(addDeclaration);
var name = declaration.name;
if (name.isEmpty) {
return;
}
if (name.endsWith('=')) {
name = name.substring(0, name.length - 1);
}
if (regExp != null && !regExp.hasMatch(name)) {
return;
}
var parent = declaration.parent;
String? className;
if (parent != null && parent.kind == ad.DeclarationKind.CLASS) {
className = parent.name;
}
String? mixinName;
if (parent != null && parent.kind == ad.DeclarationKind.MIXIN) {
mixinName = parent.name;
}
var topKind = _getTopKind(declaration.kind);
if (topKind == null) {
return;
}
declarations.add(
Declaration(
getPathIndex(path),
declaration.lineInfo,
name,
topKind,
declaration.locationOffset,
declaration.locationStartLine,
declaration.locationStartColumn,
declaration.codeOffset,
declaration.codeLength,
className,
mixinName,
declaration.parameters,
),
);
}
var libraries = tracker.allLibraries;
try {
for (var library in libraries) {
library.declarations.forEach(addDeclaration);
}
} on _MaxNumberOfDeclarationsError {
// Uses an exception to short circuit the recursion when there are too
// many declarations.
}
return declarations;
}
void _doTrackerWork() {
while (tracker.hasWork) {
tracker.doWork();
}
}
static DeclarationKind? _getTopKind(ad.DeclarationKind kind) {
switch (kind) {
case ad.DeclarationKind.CLASS:
return DeclarationKind.CLASS;
case ad.DeclarationKind.CLASS_TYPE_ALIAS:
return DeclarationKind.CLASS_TYPE_ALIAS;
case ad.DeclarationKind.CONSTRUCTOR:
return DeclarationKind.CONSTRUCTOR;
case ad.DeclarationKind.ENUM:
return DeclarationKind.ENUM;
case ad.DeclarationKind.ENUM_CONSTANT:
return DeclarationKind.ENUM_CONSTANT;
case ad.DeclarationKind.EXTENSION:
return DeclarationKind.EXTENSION;
case ad.DeclarationKind.FIELD:
return DeclarationKind.FIELD;
case ad.DeclarationKind.FUNCTION_TYPE_ALIAS:
return DeclarationKind.FUNCTION_TYPE_ALIAS;
case ad.DeclarationKind.METHOD:
return DeclarationKind.METHOD;
case ad.DeclarationKind.MIXIN:
return DeclarationKind.MIXIN;
case ad.DeclarationKind.FUNCTION:
return DeclarationKind.FUNCTION;
case ad.DeclarationKind.GETTER:
return DeclarationKind.GETTER;
case ad.DeclarationKind.SETTER:
return DeclarationKind.SETTER;
case ad.DeclarationKind.TYPE_ALIAS:
return DeclarationKind.TYPE_ALIAS;
case ad.DeclarationKind.VARIABLE:
return DeclarationKind.VARIABLE;
default:
return null;
}
}
}
/// The marker class that is thrown to stop adding declarations.
class _MaxNumberOfDeclarationsError {
const _MaxNumberOfDeclarationsError();
}