Skip to content

Commit

Permalink
fix: resolving local global functions (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelday authored Mar 24, 2019
1 parent 2c4136f commit bef52d5
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 9 deletions.
11 changes: 9 additions & 2 deletions src/DarkId.Papyrus.LanguageService/Program/SemanticExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public static IEnumerable<PapyrusSymbol> GetSymbolsInScope(this SyntaxNode node,

var symbolsInScope = symbols.
Concat(symbols.OfType<GroupSymbol>().SelectMany(g => g.Children)).Where(s => !(s is GroupSymbol)).
Concat(node.Script.Symbol.GetImportedScripts().SelectMany(s => s.GetScriptMemberSymbols(globalOnly: true)));
Concat(node.Script.Symbol.GetImportedScripts().SelectMany(s => s.GetScriptMemberSymbols(globalOnly: true))).
Concat(node.Script.Symbol.GetScriptMemberSymbols(globalOnly: true, declaredOnly: true));

if (!node.GetContainingScopes().Any(s => s is FunctionDefinitionNode || s is EventDefinitionNode))
{
Expand All @@ -67,7 +68,8 @@ public static IEnumerable<PapyrusSymbol> GetSymbolsInScope(this SyntaxNode node,
return symbolsInScope;
}

public static IEnumerable<PapyrusSymbol> GetScriptMemberSymbols(this ScriptSymbol symbol, bool declaredOnly = false, bool includeDeclaredPrivates = false, bool globalOnly = false)
public static IEnumerable<PapyrusSymbol> GetScriptMemberSymbols(
this ScriptSymbol symbol, bool declaredOnly = false, bool includeDeclaredPrivates = false, bool globalOnly = false, bool declaredGlobalsOnly = false)
{
var symbols = (IEnumerable<PapyrusSymbol>)symbol.Definition.ScopedSymbols.Values;

Expand All @@ -84,6 +86,11 @@ public static IEnumerable<PapyrusSymbol> GetScriptMemberSymbols(this ScriptSymbo
else
{
symbols = symbols.Where(s => (s.Flags & LanguageFlags.Global) != 0 && (s.Kind & SymbolKinds.Function) != 0);

if (declaredOnly)
{
symbols = symbols.Where(s => s.Script == symbol.Script);
}
}

if (!declaredOnly)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,26 @@ namespace DarkId.Papyrus.Test.LanguageService.Program
public class SemanticExtensionsTests : ProgramTestBase
{
private IEnumerable<PapyrusSymbol> GetReferencableSymbolsAtMarker(
string marker, bool assertHasResults = true, bool shouldReturnGlobals = false, string script = "ScopeTests")
string marker, bool assertHasResults = true, bool shouldReturnGlobals = false, bool canReturnDeclaredGlobals = false, string script = "ScopeTests")
{
var scopeTestScript = Program.ScriptFiles[script];
var testScript = Program.ScriptFiles[script];

var markerPosition = scopeTestScript.GetTestMarker(marker);
var node = scopeTestScript.Node.GetNodeAtPosition(markerPosition);
var markerPosition = testScript.GetTestMarker(marker);
var node = testScript.Node.GetNodeAtPosition(markerPosition);
var symbols = node.GetReferencableSymbols();

Debug.WriteLine($"Referencable symbols: {symbols.Select(s => $"{s.Name} ({s.Kind})").Join(",\r\n")}");

if (shouldReturnGlobals)
if (canReturnDeclaredGlobals)
{
var globalSymbols = symbols.Where(s => (s.Flags & LanguageFlags.Global) != 0);
if (globalSymbols.Any())
{
Assert.IsTrue(globalSymbols.All(s => s.Script.Id == testScript.Id),
"Only locally declared globals should be referencable in this case.");
}
}
else if (shouldReturnGlobals)
{
Assert.IsTrue(symbols.All(s => (s.Flags & LanguageFlags.Global) != 0), "Only globals should be referencable in this case.");
}
Expand Down Expand Up @@ -63,9 +72,10 @@ public void GetReferencableSymbols_ScriptBody()
[TestMethod]
public void GetReferencableSymbols_FunctionBody()
{
var symbols = GetReferencableSymbolsAtMarker("function-body");
var symbols = GetReferencableSymbolsAtMarker("function-body", canReturnDeclaredGlobals: true);
symbols.AssertAreOfKinds(SymbolKinds.Script | SymbolKinds.Struct | SymbolKinds.Function | SymbolKinds.Variable | SymbolKinds.Property);

Assert.IsNotNull(symbols.SingleOrDefault(s => s.Name == "LocalGlobalFunction"));
#if FALLOUT4
Assert.IsNotNull(symbols.SingleOrDefault(s => s.Name == "GroupProperty"));
#endif
Expand All @@ -74,7 +84,7 @@ public void GetReferencableSymbols_FunctionBody()
[TestMethod]
public void GetReferencableSymbols_NativeFunctionBody()
{
var symbols = GetReferencableSymbolsAtMarker("native-function-body", script: "ScriptObject");
var symbols = GetReferencableSymbolsAtMarker("native-function-body", script: "ScriptObject", canReturnDeclaredGlobals: true);
symbols.AssertAreOfKinds(SymbolKinds.Script | SymbolKinds.Struct | SymbolKinds.Function | SymbolKinds.Variable | SymbolKinds.Event | SymbolKinds.Property);
}

Expand Down
5 changes: 5 additions & 0 deletions src/DarkId.Papyrus.Test/scripts/Fallout 4/ScopeTests.psc
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ int Function ReturningIntFunction(;/marker:function-parameter-type/;int\
var ;/marker:local-variable-name/;value = 0 as ;/marker:as-expression/;int
;/marker:function-body/;
bool isInt = value is ;/marker:is-expression/;int

return arg
EndFunction

Function CallingFunction()
int a = ;/marker:assignment/;ReturningIntFunction(;/marker:function-call-parameter/;0)
EndFunction

Function LocalGlobalFunction() Global

EndFunction
4 changes: 4 additions & 0 deletions src/DarkId.Papyrus.Test/scripts/Skyrim/ScopeTests.psc
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ EndFunction

Function CallingFunction()
int a = ;/marker:assignment/;ReturningIntFunction(;/marker:function-call-parameter/;0)
EndFunction

Function LocalGlobalFunction() Global

EndFunction

0 comments on commit bef52d5

Please sign in to comment.