Skip to content

Commit

Permalink
[vscode] Go to definition jumps to the start of definition.
Browse files Browse the repository at this point in the history
Instead of "No definition found".
  • Loading branch information
pfusik committed Apr 20, 2024
1 parent ad6c819 commit 645186a
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 82 deletions.
3 changes: 3 additions & 0 deletions AST.fu
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ public abstract class FuName : FuExpr
{
internal string() Name = "";
public override int GetLocLength() => this.Name.Length;
public abstract FuSymbol? GetSymbol();
}

public abstract class FuSymbol : FuName
Expand All @@ -347,6 +348,7 @@ public abstract class FuSymbol : FuName
internal FuSymbol!? Next;
internal FuScope!? Parent;
internal FuCodeDoc#? Documentation = null;
public override FuSymbol? GetSymbol() => this;
public override string() ToString() => this.Name;
}

Expand Down Expand Up @@ -592,6 +594,7 @@ public class FuSymbolReference : FuName
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitSymbolReference(this, parent); }
public override bool IsReferenceTo(FuSymbol symbol) => this.Symbol == symbol;
public override bool IsNewString(bool substringOffset) => this.Symbol.Id == FuId.MatchValue;
public override FuSymbol? GetSymbol() => this.Symbol;
public override string() ToString() => this.Left != null ? $"{this.Left}.{this.Name}" : this.Name;
}

Expand Down
48 changes: 28 additions & 20 deletions Parser.fu
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class FuParser : FuLexer
string() FindDefinitionFilename;
int FindDefinitionLine = -1;
int FindDefinitionColumn;
FuSymbolReference? FoundDefinition = null;
FuName? FoundDefinition = null;

public void FindDefinition!(string filename, int line, int column)
{
Expand All @@ -39,9 +39,9 @@ public class FuParser : FuLexer

public string? GetFoundDefinitionFilename!()
{
if (this.FoundDefinition == null || this.FoundDefinition.Symbol == null)
if (this.FoundDefinition == null || this.FoundDefinition.GetSymbol() == null)
return null;
int loc = this.FoundDefinition.Symbol.Loc;
int loc = this.FoundDefinition.GetSymbol().Loc;
if (loc <= 0)
return null;
int line = this.Host.Program.GetLine(loc);
Expand Down Expand Up @@ -200,18 +200,23 @@ public class FuParser : FuLexer
return result;
}

void ParseSymbolReference!(FuSymbolReference! result)
bool IsFindDefinition()
{
FuSourceFile file = this.Host.Program.SourceFiles.Last();
if (this.Host.Program.LineLocs.Count - file.Line - 1 == this.FindDefinitionLine && file.Filename == this.FindDefinitionFilename) {
int loc = this.Host.Program.LineLocs.Last() + this.FindDefinitionColumn;
if (loc >= this.TokenLoc && loc <= this.Loc)
this.FoundDefinition = result;
return loc >= this.TokenLoc && loc <= this.Loc;
}
return false;
}

bool ParseName!(FuName! result)
{
if (IsFindDefinition())
this.FoundDefinition = result;
result.Loc = this.TokenLoc;
result.Name = this.StringValue;
Expect(FuToken.Id);
return Expect(FuToken.Id);
}

void ParseCollection!(List<FuExpr#>! result, FuToken closing)
Expand Down Expand Up @@ -278,7 +283,7 @@ public class FuParser : FuLexer
break;
case FuToken.Id:
FuSymbolReference# symbol = new FuSymbolReference();
ParseSymbolReference(symbol);
ParseName(symbol);
if (Eat(FuToken.FatArrow)) {
FuLambdaExpr# lambda = new FuLambdaExpr { Loc = symbol.Loc };
lambda.Add(FuVar.New(null, symbol.Name));
Expand Down Expand Up @@ -323,7 +328,7 @@ public class FuParser : FuLexer
case FuToken.Dot:
NextToken();
FuSymbolReference# path = new FuSymbolReference { Left = result };
ParseSymbolReference(path);
ParseName(path);
result = path;
break;
case FuToken.LeftParenthesis:
Expand Down Expand Up @@ -514,7 +519,7 @@ public class FuParser : FuLexer
do {
int loc = this.TokenLoc;
FuSymbolReference# field = new FuSymbolReference();
ParseSymbolReference(field);
ParseName(field);
Expect(FuToken.Assign);
result.Items.Add(new FuBinaryExpr { Loc = loc, Left = field, Op = FuToken.Assign, Right = ParseExpr() });
} while (Eat(FuToken.Comma));
Expand Down Expand Up @@ -836,7 +841,7 @@ public class FuParser : FuLexer
FuThrow# result = new FuThrow { Loc = this.TokenLoc };
Expect(FuToken.Throw);
result.Class = new FuSymbolReference();
ParseSymbolReference(result.Class);
ParseName(result.Class);
ExpectOrSkip(FuToken.LeftParenthesis);
result.Message = See(FuToken.RightParenthesis) ? null : ParseExpr();
Expect(FuToken.RightParenthesis);
Expand Down Expand Up @@ -944,7 +949,7 @@ public class FuParser : FuLexer
}
else
decl.Documentation = throwsDoc;
ParseSymbolReference(decl);
ParseName(decl);
method.Throws.Add(decl);
} while (Eat(FuToken.Comma));
}
Expand Down Expand Up @@ -982,11 +987,11 @@ public class FuParser : FuLexer
void ParseClass!(FuCodeDoc# doc, int line, int column, bool isPublic, FuCallType callType)
{
Expect(FuToken.Class);
FuClass# klass = new FuClass { Loc = this.TokenLoc, Documentation = doc, StartLine = line, StartColumn = column, IsPublic = isPublic, CallType = callType, Name = this.StringValue };
if (Expect(FuToken.Id))
FuClass# klass = new FuClass { Documentation = doc, StartLine = line, StartColumn = column, IsPublic = isPublic, CallType = callType };
if (ParseName(klass))
AddSymbol(this.Host.Program, klass);
if (Eat(FuToken.Colon))
ParseSymbolReference(klass.BaseClass);
ParseName(klass.BaseClass);
Expect(FuToken.LeftBrace);

while (!See(FuToken.RightBrace) && !See(FuToken.EndOfFile)) {
Expand Down Expand Up @@ -1051,6 +1056,7 @@ public class FuParser : FuLexer
continue;
}

bool foundDefinition = IsFindDefinition();
int loc = this.TokenLoc;
string() name = this.StringValue;
if (!Expect(FuToken.Id))
Expand Down Expand Up @@ -1082,6 +1088,8 @@ public class FuParser : FuLexer
FuMethod# method = new FuMethod { StartLine = line, StartColumn = column, Loc = loc, Documentation = doc,
Visibility = visibility, CallType = callType, TypeExpr = type, Name = name };
ParseMethod(klass, method);
if (foundDefinition)
this.FoundDefinition = method;
continue;
}

Expand All @@ -1096,6 +1104,8 @@ public class FuParser : FuLexer
Visibility = visibility, TypeExpr = type, Name = name, Value = ParseInitializer() };
AddSymbol(klass, field);
CloseMember(FuToken.Semicolon, field);
if (foundDefinition)
this.FoundDefinition = field;
}
CloseContainer(klass);
}
Expand All @@ -1108,17 +1118,15 @@ public class FuParser : FuLexer
enu.Documentation = doc;
enu.StartLine = line;
enu.StartColumn = column;
enu.Loc = this.TokenLoc;
enu.IsPublic = isPublic;
enu.Name = this.StringValue;
if (Expect(FuToken.Id))
if (ParseName(enu))
AddSymbol(this.Host.Program, enu);
Expect(FuToken.LeftBrace);
do {
FuConst# konst = new FuConst { Visibility = FuVisibility.Public, Documentation = ParseDoc(), Loc = this.TokenLoc, Name = this.StringValue, Type = enu, VisitStatus = FuVisitStatus.NotYet };
FuConst# konst = new FuConst { Visibility = FuVisibility.Public, Documentation = ParseDoc(), Type = enu, VisitStatus = FuVisitStatus.NotYet };
konst.StartLine = GetCurrentLine();
konst.StartColumn = GetTokenColumn();
Expect(FuToken.Id);
ParseName(konst);
if (Eat(FuToken.Assign))
konst.Value = ParseExpr();
else if (flags)
Expand Down
57 changes: 36 additions & 21 deletions libfut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,11 @@ int FuName::getLocLength() const
return std::ssize(this->name);
}

const FuSymbol * FuSymbol::getSymbol() const
{
return this;
}

std::string FuSymbol::toString() const
{
return this->name;
Expand Down Expand Up @@ -1488,6 +1493,11 @@ bool FuSymbolReference::isNewString(bool substringOffset) const
return this->symbol->id == FuId::matchValue;
}

const FuSymbol * FuSymbolReference::getSymbol() const
{
return this->symbol;
}

std::string FuSymbolReference::toString() const
{
return std::string(this->left != nullptr ? std::format("{}.{}", this->left->toString(), this->name) : this->name);
Expand Down Expand Up @@ -2990,9 +3000,9 @@ void FuParser::findDefinition(std::string_view filename, int line, int column)

std::string_view FuParser::getFoundDefinitionFilename()
{
if (this->foundDefinition == nullptr || this->foundDefinition->symbol == nullptr)
if (this->foundDefinition == nullptr || this->foundDefinition->getSymbol() == nullptr)
return std::string_view();
int loc = this->foundDefinition->symbol->loc;
int loc = this->foundDefinition->getSymbol()->loc;
if (loc <= 0)
return std::string_view();
int line = this->host->program->getLine(loc);
Expand Down Expand Up @@ -3178,17 +3188,23 @@ std::shared_ptr<FuExpr> FuParser::parseParenthesized()
return result;
}

void FuParser::parseSymbolReference(FuSymbolReference * result)
bool FuParser::isFindDefinition() const
{
const FuSourceFile * file = &static_cast<const FuSourceFile &>(this->host->program->sourceFiles.back());
if (std::ssize(this->host->program->lineLocs) - file->line - 1 == this->findDefinitionLine && file->filename == this->findDefinitionFilename) {
int loc = this->host->program->lineLocs.back() + this->findDefinitionColumn;
if (loc >= this->tokenLoc && loc <= this->loc)
this->foundDefinition = result;
return loc >= this->tokenLoc && loc <= this->loc;
}
return false;
}

bool FuParser::parseName(FuName * result)
{
if (isFindDefinition())
this->foundDefinition = result;
result->loc = this->tokenLoc;
result->name = this->stringValue;
expect(FuToken::id);
return expect(FuToken::id);
}

void FuParser::parseCollection(std::vector<std::shared_ptr<FuExpr>> * result, FuToken closing)
Expand Down Expand Up @@ -3293,7 +3309,7 @@ std::shared_ptr<FuExpr> FuParser::parsePrimaryExpr(bool type)
case FuToken::id:
{
std::shared_ptr<FuSymbolReference> symbol = std::make_shared<FuSymbolReference>();
parseSymbolReference(symbol.get());
parseName(symbol.get());
if (eat(FuToken::fatArrow)) {
std::shared_ptr<FuLambdaExpr> lambda = std::make_shared<FuLambdaExpr>();
lambda->loc = symbol->loc;
Expand Down Expand Up @@ -3345,7 +3361,7 @@ std::shared_ptr<FuExpr> FuParser::parsePrimaryExpr(bool type)
{
std::shared_ptr<FuSymbolReference> path = std::make_shared<FuSymbolReference>();
path->left = result;
parseSymbolReference(path.get());
parseName(path.get());
result = path;
break;
}
Expand Down Expand Up @@ -3640,7 +3656,7 @@ std::shared_ptr<FuAggregateInitializer> FuParser::parseObjectLiteral()
do {
int loc = this->tokenLoc;
std::shared_ptr<FuSymbolReference> field = std::make_shared<FuSymbolReference>();
parseSymbolReference(field.get());
parseName(field.get());
expect(FuToken::assign);
std::shared_ptr<FuBinaryExpr> futemp0 = std::make_shared<FuBinaryExpr>();
futemp0->loc = loc;
Expand Down Expand Up @@ -4008,7 +4024,7 @@ std::shared_ptr<FuThrow> FuParser::parseThrow()
result->loc = this->tokenLoc;
expect(FuToken::throw_);
result->class_ = std::make_shared<FuSymbolReference>();
parseSymbolReference(result->class_.get());
parseName(result->class_.get());
expectOrSkip(FuToken::leftParenthesis);
result->message = see(FuToken::rightParenthesis) ? nullptr : parseExpr();
expect(FuToken::rightParenthesis);
Expand Down Expand Up @@ -4120,7 +4136,7 @@ void FuParser::parseMethod(FuClass * klass, std::shared_ptr<FuMethod> method)
}
else
decl->documentation = throwsDoc;
parseSymbolReference(decl.get());
parseName(decl.get());
method->throws.push_back(decl);
}
while (eat(FuToken::comma));
Expand Down Expand Up @@ -4166,17 +4182,15 @@ void FuParser::parseClass(std::shared_ptr<FuCodeDoc> doc, int line, int column,
{
expect(FuToken::class_);
std::shared_ptr<FuClass> klass = std::make_shared<FuClass>();
klass->loc = this->tokenLoc;
klass->documentation = doc;
klass->startLine = line;
klass->startColumn = column;
klass->isPublic = isPublic;
klass->callType = callType;
klass->name = this->stringValue;
if (expect(FuToken::id))
if (parseName(klass.get()))
addSymbol(this->host->program, klass);
if (eat(FuToken::colon))
parseSymbolReference(&klass->baseClass);
parseName(&klass->baseClass);
expect(FuToken::leftBrace);
while (!see(FuToken::rightBrace) && !see(FuToken::endOfFile)) {
doc = parseDoc();
Expand Down Expand Up @@ -4243,6 +4257,7 @@ void FuParser::parseClass(std::shared_ptr<FuCodeDoc> doc, int line, int column,
klass->constructor->body = parseBlock(klass->constructor.get());
continue;
}
bool foundDefinition = isFindDefinition();
int loc = this->tokenLoc;
std::string name{this->stringValue};
if (!expect(FuToken::id))
Expand All @@ -4268,6 +4283,8 @@ void FuParser::parseClass(std::shared_ptr<FuCodeDoc> doc, int line, int column,
method->typeExpr = type;
method->name = name;
parseMethod(klass.get(), method);
if (foundDefinition)
this->foundDefinition = method.get();
continue;
}
if (visibility == FuVisibility::public_)
Expand All @@ -4287,6 +4304,8 @@ void FuParser::parseClass(std::shared_ptr<FuCodeDoc> doc, int line, int column,
field->value = parseInitializer();
addSymbol(klass.get(), field);
closeMember(FuToken::semicolon, field.get());
if (foundDefinition)
this->foundDefinition = field.get();
}
closeContainer(klass.get());
}
Expand All @@ -4299,23 +4318,19 @@ void FuParser::parseEnum(std::shared_ptr<FuCodeDoc> doc, int line, int column, b
enu->documentation = doc;
enu->startLine = line;
enu->startColumn = column;
enu->loc = this->tokenLoc;
enu->isPublic = isPublic;
enu->name = this->stringValue;
if (expect(FuToken::id))
if (parseName(enu.get()))
addSymbol(this->host->program, enu);
expect(FuToken::leftBrace);
do {
std::shared_ptr<FuConst> konst = std::make_shared<FuConst>();
konst->visibility = FuVisibility::public_;
konst->documentation = parseDoc();
konst->loc = this->tokenLoc;
konst->name = this->stringValue;
konst->type = enu;
konst->visitStatus = FuVisitStatus::notYet;
konst->startLine = getCurrentLine();
konst->startColumn = getTokenColumn();
expect(FuToken::id);
parseName(konst.get());
if (eat(FuToken::assign))
konst->value = parseExpr();
else if (flags)
Expand Down
Loading

0 comments on commit 645186a

Please sign in to comment.