mirror of https://github.com/AMT-Cheif/drift.git
Use existing parser code for auto-complete
This works very well when the user is typing at the end of a statement, but won't provide accurate results when editing in the middle.
This commit is contained in:
parent
b684a7be69
commit
ab787b82be
|
@ -1,7 +1,8 @@
|
||||||
import 'package:analyzer/dart/element/type.dart';
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
|
|
||||||
bool isFromMoor(DartType type) {
|
bool isFromMoor(DartType type) {
|
||||||
return type.element.library.location.components.first.contains('moor');
|
return type.element?.library?.location?.components?.first?.contains('moor') ??
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isColumn(DartType type) {
|
bool isColumn(DartType type) {
|
||||||
|
|
|
@ -11,4 +11,34 @@ abstract class HintDescription {
|
||||||
factory HintDescription.token(TokenType type) = TokensDescription.single;
|
factory HintDescription.token(TokenType type) = TokensDescription.single;
|
||||||
|
|
||||||
Iterable<Suggestion> suggest(CalculationRequest request);
|
Iterable<Suggestion> suggest(CalculationRequest request);
|
||||||
|
|
||||||
|
HintDescription mergeWith(HintDescription other) {
|
||||||
|
return CombinedDescription()
|
||||||
|
..descriptions.add(this)
|
||||||
|
..descriptions.add(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A [HintDescription] that bundles multiple independent [HintDescription]s.
|
||||||
|
class CombinedDescription extends HintDescription {
|
||||||
|
/// The descriptions to consult when using [suggest]. This list may be
|
||||||
|
/// modified at runtime.
|
||||||
|
final List<HintDescription> descriptions = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Suggestion> suggest(CalculationRequest request) {
|
||||||
|
return descriptions.expand((s) => s.suggest(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
HintDescription mergeWith(HintDescription other) {
|
||||||
|
if (other is CombinedDescription) {
|
||||||
|
// optimization: flatten into single list
|
||||||
|
descriptions.addAll(other.descriptions);
|
||||||
|
} else {
|
||||||
|
descriptions.add(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,17 @@ class AutoCompleteEngine {
|
||||||
} else {
|
} else {
|
||||||
// ensure that the hints list stays sorted by offset
|
// ensure that the hints list stays sorted by offset
|
||||||
final position = _lastHintBefore(hint.offset);
|
final position = _lastHintBefore(hint.offset);
|
||||||
|
final hintBefore = _hints[position];
|
||||||
|
|
||||||
|
// if we already have a hint at this position, merge them together
|
||||||
|
if (hintBefore.before == hint.before) {
|
||||||
|
hintBefore.description =
|
||||||
|
hintBefore.description.mergeWith(hint.description);
|
||||||
|
} else {
|
||||||
_hints.insert(position + 1, hint);
|
_hints.insert(position + 1, hint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AutoCompleteEngine(this._tokens) {
|
AutoCompleteEngine(this._tokens) {
|
||||||
_hintsView = UnmodifiableListView(_hints);
|
_hintsView = UnmodifiableListView(_hints);
|
||||||
|
@ -100,7 +108,7 @@ class Hint {
|
||||||
|
|
||||||
int get offset => before?.span?.end?.offset ?? 0;
|
int get offset => before?.span?.end?.offset ?? 0;
|
||||||
|
|
||||||
final HintDescription description;
|
HintDescription description;
|
||||||
|
|
||||||
Hint(this.before, this.description);
|
Hint(this.before, this.description);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,17 +53,33 @@ abstract class ParserBase {
|
||||||
|
|
||||||
ParserBase(this.tokens, this.enableMoorExtensions, this.autoComplete);
|
ParserBase(this.tokens, this.enableMoorExtensions, this.autoComplete);
|
||||||
|
|
||||||
|
bool get _reportAutoComplete => autoComplete != null;
|
||||||
|
|
||||||
void _suggestHint(HintDescription description) {
|
void _suggestHint(HintDescription description) {
|
||||||
final tokenBefore = _current == 0 ? null : _previous;
|
final tokenBefore = _current == 0 ? null : _previous;
|
||||||
autoComplete?.addHint(Hint(tokenBefore, description));
|
autoComplete?.addHint(Hint(tokenBefore, description));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _suggestHintForTokens(Iterable<TokenType> types) {
|
||||||
|
final relevant =
|
||||||
|
types.where(isKeyword).map((type) => HintDescription.token(type));
|
||||||
|
final description = CombinedDescription()..descriptions.addAll(relevant);
|
||||||
|
_suggestHint(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _suggestHintForToken(TokenType type) {
|
||||||
|
if (isKeyword(type)) {
|
||||||
|
_suggestHint(HintDescription.token(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool get _isAtEnd => _peek.type == TokenType.eof;
|
bool get _isAtEnd => _peek.type == TokenType.eof;
|
||||||
Token get _peek => tokens[_current];
|
Token get _peek => tokens[_current];
|
||||||
Token get _peekNext => tokens[_current + 1];
|
Token get _peekNext => tokens[_current + 1];
|
||||||
Token get _previous => tokens[_current - 1];
|
Token get _previous => tokens[_current - 1];
|
||||||
|
|
||||||
bool _match(Iterable<TokenType> types) {
|
bool _match(Iterable<TokenType> types) {
|
||||||
|
if (_reportAutoComplete) _suggestHintForTokens(types);
|
||||||
for (var type in types) {
|
for (var type in types) {
|
||||||
if (_check(type)) {
|
if (_check(type)) {
|
||||||
_advance();
|
_advance();
|
||||||
|
@ -74,6 +90,7 @@ abstract class ParserBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _matchOne(TokenType type) {
|
bool _matchOne(TokenType type) {
|
||||||
|
if (_reportAutoComplete) _suggestHintForToken(type);
|
||||||
if (_check(type)) {
|
if (_check(type)) {
|
||||||
_advance();
|
_advance();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -257,6 +257,9 @@ const Map<String, TokenType> moorKeywords = {
|
||||||
'IMPORT': TokenType.import,
|
'IMPORT': TokenType.import,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Returns true if the [type] belongs to a keyword
|
||||||
|
bool isKeyword(TokenType type) => reverseKeywords.containsKey(type);
|
||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
final TokenType type;
|
final TokenType type;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue