blob: 1c9e0f454f105e0d1dd58351f23528484f5ac25c [file] [log] [blame]
// Copyright (c) 2017, 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:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
import 'package:kernel/ast.dart' show Expression;
import '../builder/builder.dart';
import '../builder/type_builder.dart';
import '../kernel/expression_generator.dart';
import 'operator.dart';
import 'problems.dart' show unhandled, unsupported;
abstract class Identifier {
Token get token;
String get name;
/// The left-most offset of this identifier.
int get firstOffset;
/// The offset of the qualifier if this identifier is a [QualifiedName].
/// Otherwise the [nameOffset].
int get qualifierOffset;
/// The offset of the simple name of this identifier. If this is a
/// [QualifiedName], this is the offset of the suffix.
int get nameOffset;
Expression? get initializer;
Operator? get operator;
TypeName get typeName;
}
abstract class IdentifierImpl implements Identifier {
@override
final Token token;
IdentifierImpl(this.token);
@override
String get name => token.lexeme;
int get charOffset => token.charOffset;
@override
int get firstOffset => charOffset;
@override
int get qualifierOffset => charOffset;
@override
int get nameOffset => charOffset;
@override
Expression? get initializer => null;
@override
Operator? get operator => null;
@override
TypeName get typeName => new IdentifierTypeName(name, nameOffset);
@override
String toString() => "IdentifierImpl($name)";
}
class SimpleIdentifier extends IdentifierImpl {
SimpleIdentifier(super.token);
QualifiedNameIdentifier withIdentifierQualifier(Identifier qualifier) {
return new QualifiedNameIdentifier(qualifier, token);
}
QualifiedNameGenerator withGeneratorQualifier(Generator qualifier) {
return new QualifiedNameGenerator(qualifier, token);
}
QualifiedNameBuilder withBuilderQualifier(Builder qualifier) {
return new QualifiedNameBuilder(qualifier, token);
}
@override
String toString() => "SimpleIdentifier($name)";
}
class OperatorIdentifier implements Identifier {
@override
final Token token;
@override
final Operator operator;
OperatorIdentifier(this.token)
: this.operator = Operator.fromText(token.stringValue!)!;
@override
String get name => operator.text;
// Coverage-ignore(suite): Not run.
int get charOffset => token.charOffset;
@override
// Coverage-ignore(suite): Not run.
int get firstOffset => token.charOffset;
@override
int get qualifierOffset => token.charOffset;
@override
int get nameOffset => token.charOffset;
@override
// Coverage-ignore(suite): Not run.
Expression? get initializer => null;
@override
// Coverage-ignore(suite): Not run.
TypeName get typeName {
return unsupported("typeName", charOffset, null);
}
@override
String toString() => "Operator($name)";
}
class InitializedIdentifier extends SimpleIdentifier {
@override
final Expression initializer;
InitializedIdentifier(Identifier identifier, this.initializer)
: super(identifier.token);
@override
// Coverage-ignore(suite): Not run.
TypeName get typeName {
return unsupported("typeName", charOffset, null);
}
@override
String toString() => "initialized-identifier($name, $initializer)";
}
sealed class QualifiedName extends IdentifierImpl {
QualifiedName(Token suffix) : super(suffix);
}
class QualifiedNameIdentifier extends QualifiedName {
final Identifier qualifier;
QualifiedNameIdentifier(this.qualifier, Token suffix) : super(suffix);
// Coverage-ignore(suite): Not run.
Token get suffix => token;
@override
int get firstOffset => qualifier.firstOffset;
@override
int get qualifierOffset => qualifier.nameOffset;
@override
int get nameOffset => token.charOffset;
@override
TypeName get typeName =>
new QualifiedTypeName(qualifier.name, qualifierOffset, name, nameOffset);
@override
String toString() => "qualified-name-identifier($qualifier, $name)";
}
class QualifiedNameGenerator extends QualifiedName {
final Generator qualifier;
QualifiedNameGenerator(this.qualifier, Token suffix) : super(suffix);
Token get suffix => token;
@override
// Coverage-ignore(suite): Not run.
int get firstOffset => qualifier.fileOffset;
@override
String toString() => "qualified-name-generator($qualifier, $name)";
}
class QualifiedNameBuilder extends QualifiedName {
final Builder qualifier;
QualifiedNameBuilder(this.qualifier, Token suffix) : super(suffix);
Token get suffix => token;
@override
// Coverage-ignore(suite): Not run.
int get firstOffset => qualifier.fileOffset;
@override
String toString() => "qualified-name-builder($qualifier, $name)";
}
void flattenQualifiedNameOn(
QualifiedName name, StringBuffer buffer, int charOffset, Uri? fileUri) {
switch (name) {
case QualifiedNameIdentifier():
Identifier qualifier = name.qualifier;
if (qualifier is QualifiedName) {
flattenQualifiedNameOn(qualifier, buffer, charOffset, fileUri);
} else {
buffer.write(qualifier.name);
}
// Coverage-ignore(suite): Not run.
case QualifiedNameGenerator():
case QualifiedNameBuilder():
unhandled(
"${name.runtimeType}", "flattenQualifiedNameOn", charOffset, fileUri);
}
buffer.write(".");
buffer.write(name.name);
}
String flattenName(Identifier name, int charOffset, Uri? fileUri) {
if (name is QualifiedName) {
StringBuffer buffer = new StringBuffer();
flattenQualifiedNameOn(name, buffer, charOffset, fileUri);
return "$buffer";
} else {
return name.name;
}
}