diff --git a/src/DarkId.Papyrus.LanguageService/Program/SemanticExtensions.cs b/src/DarkId.Papyrus.LanguageService/Program/SemanticExtensions.cs index 1e856ee5..3c4097ac 100644 --- a/src/DarkId.Papyrus.LanguageService/Program/SemanticExtensions.cs +++ b/src/DarkId.Papyrus.LanguageService/Program/SemanticExtensions.cs @@ -57,7 +57,8 @@ public static IEnumerable GetSymbolsInScope(this SyntaxNode node, var symbolsInScope = symbols. Concat(symbols.OfType().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)) { @@ -67,7 +68,8 @@ public static IEnumerable GetSymbolsInScope(this SyntaxNode node, return symbolsInScope; } - public static IEnumerable GetScriptMemberSymbols(this ScriptSymbol symbol, bool declaredOnly = false, bool includeDeclaredPrivates = false, bool globalOnly = false) + public static IEnumerable GetScriptMemberSymbols( + this ScriptSymbol symbol, bool declaredOnly = false, bool includeDeclaredPrivates = false, bool globalOnly = false, bool declaredGlobalsOnly = false) { var symbols = (IEnumerable)symbol.Definition.ScopedSymbols.Values; @@ -84,6 +86,11 @@ public static IEnumerable 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) diff --git a/src/DarkId.Papyrus.Test/LanguageService/Program/SemanticExtensionsTests.cs b/src/DarkId.Papyrus.Test/LanguageService/Program/SemanticExtensionsTests.cs index e3b088b3..a0864f24 100644 --- a/src/DarkId.Papyrus.Test/LanguageService/Program/SemanticExtensionsTests.cs +++ b/src/DarkId.Papyrus.Test/LanguageService/Program/SemanticExtensionsTests.cs @@ -17,17 +17,26 @@ namespace DarkId.Papyrus.Test.LanguageService.Program public class SemanticExtensionsTests : ProgramTestBase { private IEnumerable 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."); } @@ -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 @@ -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); } diff --git a/src/DarkId.Papyrus.Test/scripts/Fallout 4/ScopeTests.psc b/src/DarkId.Papyrus.Test/scripts/Fallout 4/ScopeTests.psc index 83c22326..bcefa5af 100644 --- a/src/DarkId.Papyrus.Test/scripts/Fallout 4/ScopeTests.psc +++ b/src/DarkId.Papyrus.Test/scripts/Fallout 4/ScopeTests.psc @@ -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 \ No newline at end of file diff --git a/src/DarkId.Papyrus.Test/scripts/Skyrim/ScopeTests.psc b/src/DarkId.Papyrus.Test/scripts/Skyrim/ScopeTests.psc index 312049d6..e25d2916 100644 --- a/src/DarkId.Papyrus.Test/scripts/Skyrim/ScopeTests.psc +++ b/src/DarkId.Papyrus.Test/scripts/Skyrim/ScopeTests.psc @@ -35,4 +35,8 @@ EndFunction Function CallingFunction() int a = ;/marker:assignment/;ReturningIntFunction(;/marker:function-call-parameter/;0) +EndFunction + +Function LocalGlobalFunction() Global + EndFunction \ No newline at end of file