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';
|
||||
|
||||
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) {
|
||||
|
|
|
@ -11,4 +11,34 @@ abstract class HintDescription {
|
|||
factory HintDescription.token(TokenType type) = TokensDescription.single;
|
||||
|
||||
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 {
|
||||
// ensure that the hints list stays sorted by 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AutoCompleteEngine(this._tokens) {
|
||||
_hintsView = UnmodifiableListView(_hints);
|
||||
|
@ -100,7 +108,7 @@ class Hint {
|
|||
|
||||
int get offset => before?.span?.end?.offset ?? 0;
|
||||
|
||||
final HintDescription description;
|
||||
HintDescription description;
|
||||
|
||||
Hint(this.before, this.description);
|
||||
}
|
||||
|
|
|
@ -53,17 +53,33 @@ abstract class ParserBase {
|
|||
|
||||
ParserBase(this.tokens, this.enableMoorExtensions, this.autoComplete);
|
||||
|
||||
bool get _reportAutoComplete => autoComplete != null;
|
||||
|
||||
void _suggestHint(HintDescription description) {
|
||||
final tokenBefore = _current == 0 ? null : _previous;
|
||||
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;
|
||||
Token get _peek => tokens[_current];
|
||||
Token get _peekNext => tokens[_current + 1];
|
||||
Token get _previous => tokens[_current - 1];
|
||||
|
||||
bool _match(Iterable<TokenType> types) {
|
||||
if (_reportAutoComplete) _suggestHintForTokens(types);
|
||||
for (var type in types) {
|
||||
if (_check(type)) {
|
||||
_advance();
|
||||
|
@ -74,6 +90,7 @@ abstract class ParserBase {
|
|||
}
|
||||
|
||||
bool _matchOne(TokenType type) {
|
||||
if (_reportAutoComplete) _suggestHintForToken(type);
|
||||
if (_check(type)) {
|
||||
_advance();
|
||||
return true;
|
||||
|
|
|
@ -257,6 +257,9 @@ const Map<String, TokenType> moorKeywords = {
|
|||
'IMPORT': TokenType.import,
|
||||
};
|
||||
|
||||
/// Returns true if the [type] belongs to a keyword
|
||||
bool isKeyword(TokenType type) => reverseKeywords.containsKey(type);
|
||||
|
||||
class Token {
|
||||
final TokenType type;
|
||||
|
||||
|
|
Loading…
Reference in New Issue