Skip to content

Commit

Permalink
[vscode] Go to definition of base class.
Browse files Browse the repository at this point in the history
  • Loading branch information
pfusik committed Apr 19, 2024
1 parent 54c4f49 commit 1b7e466
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 49 deletions.
4 changes: 2 additions & 2 deletions AST.fu
Original file line number Diff line number Diff line change
Expand Up @@ -1318,10 +1318,10 @@ public class FuClass : FuContainerType
internal FuCallType CallType;
internal int TypeParameterCount = 0;
internal bool HasSubclasses = false;
internal string() BaseClassName = "";
internal FuSymbolReference() BaseClass;
internal FuMethodBase#? Constructor;
internal List<FuConst>() ConstArrays;
public bool HasBaseClass() => this.BaseClassName.Length > 0;
public bool HasBaseClass() => this.BaseClass.Name.Length > 0;
public bool AddsVirtualMethods()
{
for (FuSymbol? symbol = this.First; symbol != null; symbol = symbol.Next) {
Expand Down
6 changes: 3 additions & 3 deletions GenCpp.fu
Original file line number Diff line number Diff line change
Expand Up @@ -1757,12 +1757,12 @@ public class GenCpp : GenCCpp
if (constructor) {
if (klass.Id == FuId.ExceptionClass) {
Write("using ");
if (klass.BaseClassName == "Exception")
if (klass.BaseClass.Name == "Exception")
Write("std::runtime_error::runtime_error");
else {
Write(klass.BaseClassName);
Write(klass.BaseClass.Name);
Write("::");
Write(klass.BaseClassName);
Write(klass.BaseClass.Name);
}
}
else {
Expand Down
8 changes: 4 additions & 4 deletions Parser.fu
Original file line number Diff line number Diff line change
Expand Up @@ -985,10 +985,10 @@ public class FuParser : FuLexer
FuClass# klass = new FuClass { Loc = this.TokenLoc, Documentation = doc, StartLine = line, StartColumn = column, IsPublic = isPublic, CallType = callType, Name = this.StringValue };
if (Expect(FuToken.Id))
AddSymbol(this.Host.Program, klass);
if (Eat(FuToken.Colon)) {
klass.BaseClassName = this.StringValue;
Expect(FuToken.Id);
}
if (Eat(FuToken.Colon))
ParseSymbolReference(klass.BaseClass);
else
klass.BaseClass.Name = "";
Expect(FuToken.LeftBrace);

while (!See(FuToken.RightBrace) && !See(FuToken.EndOfFile)) {
Expand Down
7 changes: 4 additions & 3 deletions Sema.fu
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,15 @@ public class FuSema
{
if (klass.HasBaseClass()) {
this.CurrentScope = klass;
if (this.Host.Program.TryLookup(klass.BaseClassName, true) is FuClass! baseClass) {
if (this.Host.Program.TryLookup(klass.BaseClass.Name, true) is FuClass! baseClass) {
if (klass.IsPublic && !baseClass.IsPublic)
ReportError(klass, "Public class cannot derive from an internal class");
ReportError(klass.BaseClass, "Public class cannot derive from an internal class");
klass.BaseClass.Symbol = baseClass;
baseClass.HasSubclasses = true;
klass.Parent = baseClass;
}
else
ReportError(klass, $"Base class '{klass.BaseClassName}' not found");
ReportError(klass.BaseClass, $"Base class '{klass.BaseClass.Name}' not found");
}
this.Host.Program.Classes.Add(klass);
}
Expand Down
23 changes: 12 additions & 11 deletions libfut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2326,7 +2326,7 @@ void FuEnum::acceptValues(FuVisitor * visitor) const

bool FuClass::hasBaseClass() const
{
return !this->baseClassName.empty();
return !this->baseClass.name.empty();
}

bool FuClass::addsVirtualMethods() const
Expand Down Expand Up @@ -4180,10 +4180,10 @@ void FuParser::parseClass(std::shared_ptr<FuCodeDoc> doc, int line, int column,
klass->name = this->stringValue;
if (expect(FuToken::id))
addSymbol(this->host->program, klass);
if (eat(FuToken::colon)) {
klass->baseClassName = this->stringValue;
expect(FuToken::id);
}
if (eat(FuToken::colon))
parseSymbolReference(&klass->baseClass);
else
klass->baseClass.name = "";
expect(FuToken::leftBrace);
while (!see(FuToken::rightBrace) && !see(FuToken::endOfFile)) {
doc = parseDoc();
Expand Down Expand Up @@ -4408,14 +4408,15 @@ void FuSema::resolveBase(FuClass * klass)
{
if (klass->hasBaseClass()) {
this->currentScope = klass;
if (FuClass *baseClass = dynamic_cast<FuClass *>(this->host->program->tryLookup(klass->baseClassName, true).get())) {
if (FuClass *baseClass = dynamic_cast<FuClass *>(this->host->program->tryLookup(klass->baseClass.name, true).get())) {
if (klass->isPublic && !baseClass->isPublic)
reportError(klass, "Public class cannot derive from an internal class");
reportError(&klass->baseClass, "Public class cannot derive from an internal class");
klass->baseClass.symbol = baseClass;
baseClass->hasSubclasses = true;
klass->parent = baseClass;
}
else
reportError(klass, std::format("Base class '{}' not found", klass->baseClassName));
reportError(&klass->baseClass, std::format("Base class '{}' not found", klass->baseClass.name));
}
this->host->program->classes.push_back(klass);
}
Expand Down Expand Up @@ -15063,12 +15064,12 @@ void GenCpp::writeDeclarations(const FuClass * klass, FuVisibility visibility, s
if (constructor) {
if (klass->id == FuId::exceptionClass) {
write("using ");
if (klass->baseClassName == "Exception")
if (klass->baseClass.name == "Exception")
write("std::runtime_error::runtime_error");
else {
write(klass->baseClassName);
write(klass->baseClass.name);
write("::");
write(klass->baseClassName);
write(klass->baseClass.name);
}
}
else {
Expand Down
25 changes: 13 additions & 12 deletions libfut.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2895,13 +2895,13 @@ public class FuClass : FuContainerType

internal bool HasSubclasses = false;

internal string BaseClassName = "";
internal readonly FuSymbolReference BaseClass = new FuSymbolReference();

internal FuMethodBase Constructor;

internal readonly List<FuConst> ConstArrays = new List<FuConst>();

public bool HasBaseClass() => this.BaseClassName.Length > 0;
public bool HasBaseClass() => this.BaseClass.Name.Length > 0;

public bool AddsVirtualMethods()
{
Expand Down Expand Up @@ -4459,10 +4459,10 @@ void ParseClass(FuCodeDoc doc, int line, int column, bool isPublic, FuCallType c
FuClass klass = new FuClass { Loc = this.TokenLoc, Documentation = doc, StartLine = line, StartColumn = column, IsPublic = isPublic, CallType = callType, Name = this.StringValue };
if (Expect(FuToken.Id))
AddSymbol(this.Host.Program, klass);
if (Eat(FuToken.Colon)) {
klass.BaseClassName = this.StringValue;
Expect(FuToken.Id);
}
if (Eat(FuToken.Colon))
ParseSymbolReference(klass.BaseClass);
else
klass.BaseClass.Name = "";
Expect(FuToken.LeftBrace);
while (!See(FuToken.RightBrace) && !See(FuToken.EndOfFile)) {
doc = ParseDoc();
Expand Down Expand Up @@ -4674,14 +4674,15 @@ void ResolveBase(FuClass klass)
{
if (klass.HasBaseClass()) {
this.CurrentScope = klass;
if (this.Host.Program.TryLookup(klass.BaseClassName, true) is FuClass baseClass) {
if (this.Host.Program.TryLookup(klass.BaseClass.Name, true) is FuClass baseClass) {
if (klass.IsPublic && !baseClass.IsPublic)
ReportError(klass, "Public class cannot derive from an internal class");
ReportError(klass.BaseClass, "Public class cannot derive from an internal class");
klass.BaseClass.Symbol = baseClass;
baseClass.HasSubclasses = true;
klass.Parent = baseClass;
}
else
ReportError(klass, $"Base class '{klass.BaseClassName}' not found");
ReportError(klass.BaseClass, $"Base class '{klass.BaseClass.Name}' not found");
}
this.Host.Program.Classes.Add(klass);
}
Expand Down Expand Up @@ -15401,12 +15402,12 @@ void WriteDeclarations(FuClass klass, FuVisibility visibility, string visibility
if (constructor) {
if (klass.Id == FuId.ExceptionClass) {
Write("using ");
if (klass.BaseClassName == "Exception")
if (klass.BaseClass.Name == "Exception")
Write("std::runtime_error::runtime_error");
else {
Write(klass.BaseClassName);
Write(klass.BaseClass.Name);
Write("::");
Write(klass.BaseClassName);
Write(klass.BaseClass.Name);
}
}
else {
Expand Down
2 changes: 1 addition & 1 deletion libfut.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,7 @@ class FuClass : public FuContainerType
FuCallType callType;
int typeParameterCount = 0;
bool hasSubclasses = false;
std::string baseClassName{""};
FuSymbolReference baseClass;
std::shared_ptr<FuMethodBase> constructor;
std::vector<const FuConst *> constArrays;
};
Expand Down
25 changes: 13 additions & 12 deletions libfut.js
Original file line number Diff line number Diff line change
Expand Up @@ -3015,13 +3015,13 @@ export class FuClass extends FuContainerType
callType;
typeParameterCount = 0;
hasSubclasses = false;
baseClassName = "";
baseClass = new FuSymbolReference();
constructor_;
constArrays = [];

hasBaseClass()
{
return this.baseClassName.length > 0;
return this.baseClass.name.length > 0;
}

addsVirtualMethods()
Expand Down Expand Up @@ -4666,10 +4666,10 @@ export class FuParser extends FuLexer
let klass = Object.assign(new FuClass(), { loc: this.tokenLoc, documentation: doc, startLine: line, startColumn: column, isPublic: isPublic, callType: callType, name: this.stringValue });
if (this.expect(FuToken.ID))
this.#addSymbol(this.host.program, klass);
if (this.eat(FuToken.COLON)) {
klass.baseClassName = this.stringValue;
this.expect(FuToken.ID);
}
if (this.eat(FuToken.COLON))
this.#parseSymbolReference(klass.baseClass);
else
klass.baseClass.name = "";
this.expect(FuToken.LEFT_BRACE);
while (!this.see(FuToken.RIGHT_BRACE) && !this.see(FuToken.END_OF_FILE)) {
doc = this.#parseDoc();
Expand Down Expand Up @@ -4883,14 +4883,15 @@ export class FuSema
if (klass.hasBaseClass()) {
this.#currentScope = klass;
let baseClass;
if ((baseClass = this.#host.program.tryLookup(klass.baseClassName, true)) instanceof FuClass) {
if ((baseClass = this.#host.program.tryLookup(klass.baseClass.name, true)) instanceof FuClass) {
if (klass.isPublic && !baseClass.isPublic)
this.#reportError(klass, "Public class cannot derive from an internal class");
this.#reportError(klass.baseClass, "Public class cannot derive from an internal class");
klass.baseClass.symbol = baseClass;
baseClass.hasSubclasses = true;
klass.parent = baseClass;
}
else
this.#reportError(klass, `Base class '${klass.baseClassName}' not found`);
this.#reportError(klass.baseClass, `Base class '${klass.baseClass.name}' not found`);
}
this.#host.program.classes.push(klass);
}
Expand Down Expand Up @@ -15875,12 +15876,12 @@ export class GenCpp extends GenCCpp
if (constructor) {
if (klass.id == FuId.EXCEPTION_CLASS) {
this.write("using ");
if (klass.baseClassName == "Exception")
if (klass.baseClass.name == "Exception")
this.write("std::runtime_error::runtime_error");
else {
this.write(klass.baseClassName);
this.write(klass.baseClass.name);
this.write("::");
this.write(klass.baseClassName);
this.write(klass.baseClass.name);
}
}
else {
Expand Down
3 changes: 2 additions & 1 deletion test/error/ClassBaseUndefined.fu
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
public class Test : Base //ERROR: Base class 'Base' not found
public class Test :
Base //ERROR: Base class 'Base' not found
{
public static bool Run() => true;
}

0 comments on commit 1b7e466

Please sign in to comment.