/// <summary> /// Replace the method occurence with its last definition /// </summary> /// <param name="methodDeclaration">the overriding method</param> /// <param name="errorLogger"></param> public void ReplaceVirtualMethod(MethodDeclaration methodDeclaration, LoggerResult errorLogger) { var baseDeclarationMixin = (string)methodDeclaration.GetTag(XenkoTags.BaseDeclarationMixin); foreach (var dict in VirtualTableGroup.Select(x => x.Value)) { for (int i = 0; i < dict.Length; ++i) { var method = dict[i]; var originalDecl = (string)method.GetTag(XenkoTags.BaseDeclarationMixin); // TODO: take typedefs into account... if (originalDecl == baseDeclarationMixin && method.IsSameSignature(methodDeclaration)) { if (method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && !methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Warning(XenkoMessageCode.WarningMissingStageKeyword, methodDeclaration.Span, methodDeclaration, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers |= XenkoStorageQualifier.Stage; } else if (!method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Error(XenkoMessageCode.ErrorExtraStageKeyword, methodDeclaration.Span, methodDeclaration, method, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers.Values.Remove(XenkoStorageQualifier.Stage); } dict[i] = methodDeclaration; } } } }
/// <summary> /// Finds the location of the method in the virtual table of its definition mixin /// </summary> /// <param name="methodDeclaration"></param> /// <returns></returns> public VTableReference GetBaseDeclaration(MethodDeclaration methodDeclaration) { var baseMethodDeclMixin = methodDeclaration.GetTag(XenkoTags.BaseDeclarationMixin) as string; var slot = -1; var vt = VirtualTableGroup[baseMethodDeclMixin]; for (int i = 0; i < vt.Length; ++i) { if (methodDeclaration.IsSameSignature(vt[i])) { slot = i; break; } } return new VTableReference { Shader = baseMethodDeclMixin, Slot = slot }; }
/// <summary> /// Find the base definition of the method and override its occurence /// </summary> /// <param name="methodDeclaration"></param> /// <param name="errorLogger"></param> private void LookForBaseDeclarationMixin(MethodDeclaration methodDeclaration, LoggerResult errorLogger) { foreach (var dict in VirtualTableGroup.Select(x => x.Value)) { for (int i = 0; i < dict.Length; ++i) { var method = dict[i]; var baseDeclarationMixin = (string)method.GetTag(XenkoTags.BaseDeclarationMixin); // TODO: take typedefs into account... if (method.IsSameSignature(methodDeclaration)) { var sourceShader = ((ModuleMixin)methodDeclaration.GetTag(XenkoTags.ShaderScope)).MixinName; // test override if (methodDeclaration is MethodDefinition && method is MethodDefinition && !methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Override)) errorLogger.Error(XenkoMessageCode.ErrorMissingOverride, method.Span, methodDeclaration, sourceShader); if (!(methodDeclaration is MethodDefinition)) errorLogger.Error(XenkoMessageCode.ErrorOverrindingDeclaration, method.Span, methodDeclaration, sourceShader); if (method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && !methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Warning(XenkoMessageCode.WarningMissingStageKeyword, methodDeclaration.Span, methodDeclaration, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers |= XenkoStorageQualifier.Stage; } else if (!method.Qualifiers.Contains(XenkoStorageQualifier.Stage) && methodDeclaration.Qualifiers.Contains(XenkoStorageQualifier.Stage)) { errorLogger.Error(XenkoMessageCode.ErrorExtraStageKeyword, methodDeclaration.Span, methodDeclaration, method, (methodDeclaration.GetTag(XenkoTags.ShaderScope) as ModuleMixin).MixinName); methodDeclaration.Qualifiers.Values.Remove(XenkoStorageQualifier.Stage); } dict[i] = methodDeclaration; methodDeclaration.SetTag(XenkoTags.BaseDeclarationMixin, baseDeclarationMixin); } } } }
/// <summary> /// Get the overloaded method from one of its base declaration /// </summary> /// <param name="methodDeclaration">the MethodDeclaration</param> /// <returns>the overloaded MethodDeclaration</returns> public MethodDeclaration GetMethodFromDeclaration(MethodDeclaration methodDeclaration) { var info = (VTableReference)methodDeclaration.GetTag(ParadoxTags.VirtualTableReference); return VirtualTable.GetMethod(info.Shader, info.Slot); }