public static IEnumerable <PapyrusSymbol> GetKnownParameterValueSymbols(this FunctionCallExpressionNode functionCallExpression, int parameterIndex, out bool valuesAreValidExclusively) { valuesAreValidExclusively = false; var definedFunction = functionCallExpression.GetDefinition(); var parameterDefinition = functionCallExpression.GetParameterDefinition(parameterIndex); #if FALLOUT4 if (parameterDefinition != null) { var parameterTypeName = parameterDefinition.TypeIdentifier.Text; if (parameterTypeName.CaseInsensitiveEquals("CustomEventName")) { valuesAreValidExclusively = true; return(GetKnownEventParameterSymbols <CustomEventSymbol>(functionCallExpression, parameterIndex)); } if (parameterTypeName.CaseInsensitiveEquals("ScriptEventName")) { valuesAreValidExclusively = true; return(GetKnownEventParameterSymbols <EventSymbol>(functionCallExpression, parameterIndex)); } var functionName = definedFunction.Header.Identifier.Text; if (functionName.CaseInsensitiveEquals("FindStruct") || functionName.CaseInsensitiveEquals("RFindStruct")) { if (parameterDefinition.Identifier.Text.CaseInsensitiveEquals("asVarName")) { valuesAreValidExclusively = true; var definedFunctionScriptSymbol = definedFunction.Symbol.Script; var elementTypeId = definedFunctionScriptSymbol.SyntheticArrayType?.ElementType; if (elementTypeId.HasValue) { if (functionCallExpression.GetTypeChecker().GetTypeForObjectId(elementTypeId.Value) is StructType elementType) { return(elementType.Symbol.Children); } } return(Enumerable.Empty <PapyrusSymbol>()); } } } #endif if (definedFunction.Symbol.Name.CaseInsensitiveEquals("GotoState")) { var expressionForScriptType = functionCallExpression.GetMemberAccessExpression()?.BaseExpression; var scriptType = expressionForScriptType?.GetTypeOfExpression() as ScriptType ?? functionCallExpression.Script.Symbol.GetPapyrusType() as ScriptType; return(scriptType.Symbol.GetExtendedScriptChain(true). SelectMany(scriptSymbol => scriptSymbol.Children.OfType <StateSymbol>()). DistinctBy(s => s.Name.ToLower()).ToArray()); } return(Enumerable.Empty <PapyrusSymbol>()); }
private static IEnumerable <PapyrusSymbol> GetKnownEventParameterSymbols <T>(FunctionCallExpressionNode functionCallExpression, int parameterIndex) where T : PapyrusSymbol { // If the event name parameter is not the first parameter: // We assume that the first parameter's expression result is of the source type. // If it *is* the first parameter: // The defined function most likely lives on ScriptObject, so we need to find the derived type that is the subject of the call. // So, either the source type is the base expression of the parent member access expression, -or-, if there is no member access expression, // then it must be the current script type. var expressionForSourceType = parameterIndex > 0 ? functionCallExpression.Parameters.ElementAtOrDefault(0).Value : functionCallExpression.GetMemberAccessExpression()?.BaseExpression; var sourceType = expressionForSourceType?.GetTypeOfExpression() as ScriptType ?? functionCallExpression.Script.Symbol.GetPapyrusType() as ScriptType; // CustomEventNames can be inherited, so the symbols are sourced from the full extended script chain return(sourceType.Symbol.GetExtendedScriptChain(true).SelectMany(scriptSymbol => scriptSymbol.Children.OfType <T>()).ToArray()); }