MemberList GetMemberList() { var result = LazyInit.VolatileRead(ref this.memberList); if (result != null) { return(result); } List <IUnresolvedMember> unresolvedMembers = new List <IUnresolvedMember>(); List <ITypeResolveContext> contextPerMember = new List <ITypeResolveContext>(); List <PartialMethodInfo> partialMethodInfos = null; bool addDefaultConstructorIfRequired = false; foreach (IUnresolvedTypeDefinition part in parts) { ITypeResolveContext parentContextForPart = part.CreateResolveContext(parentContext); ITypeResolveContext contextForPart = parentContextForPart.WithCurrentTypeDefinition(this); foreach (var member in part.Members) { if (member is IUnresolvedMethod method && method.IsPartial) { // Merge partial method declaration and implementation if (partialMethodInfos == null) { partialMethodInfos = new List <PartialMethodInfo>(); } PartialMethodInfo newInfo = new PartialMethodInfo(method, contextForPart); PartialMethodInfo existingInfo = null; foreach (var info in partialMethodInfos) { if (newInfo.IsSameSignature(info, Compilation.NameComparer)) { existingInfo = info; break; } } if (existingInfo != null) { // Add the unresolved method to the PartialMethodInfo: existingInfo.AddPart(method, contextForPart); } else { partialMethodInfos.Add(newInfo); } }
MemberList GetMemberList() { var result = LazyInit.VolatileRead(ref this.memberList); if (result != null) { return(result); } List <IUnresolvedMember> unresolvedMembers = new List <IUnresolvedMember>(); List <ITypeResolveContext> contextPerMember = new List <ITypeResolveContext>(); List <PartialMethodInfo> partialMethodInfos = null; bool addDefaultConstructorIfRequired = false; foreach (IUnresolvedTypeDefinition part in parts) { ITypeResolveContext parentContextForPart = part.CreateResolveContext(parentContext); ITypeResolveContext contextForPart = parentContextForPart.WithCurrentTypeDefinition(this); foreach (var member in part.Members) { IUnresolvedMethod method = member as IUnresolvedMethod; if (method != null && method.IsPartial) { // Merge partial method declaration and implementation if (partialMethodInfos == null) { partialMethodInfos = new List <PartialMethodInfo>(); } PartialMethodInfo newInfo = new PartialMethodInfo(method, contextForPart); PartialMethodInfo existingInfo = null; foreach (var info in partialMethodInfos) { if (newInfo.IsSameSignature(info, Compilation.NameComparer)) { existingInfo = info; break; } } if (existingInfo != null) { // Add the unresolved method to the PartialMethodInfo: existingInfo.AddPart(method, contextForPart); } else { partialMethodInfos.Add(newInfo); } } else { unresolvedMembers.Add(member); contextPerMember.Add(contextForPart); } } addDefaultConstructorIfRequired |= part.AddDefaultConstructorIfRequired; } if (addDefaultConstructorIfRequired) { TypeKind kind = this.Kind; if (kind == TypeKind.Class && !this.IsStatic && !unresolvedMembers.Any(m => m.SymbolKind == SymbolKind.Constructor && !m.IsStatic) || kind == TypeKind.Enum || kind == TypeKind.Struct) { contextPerMember.Add(parts[0].CreateResolveContext(parentContext).WithCurrentTypeDefinition(this)); unresolvedMembers.Add(DefaultUnresolvedMethod.CreateDefaultConstructor(parts[0])); } } result = new MemberList(contextPerMember, unresolvedMembers, partialMethodInfos); return(LazyInit.GetOrSet(ref this.memberList, result)); }
public bool IsSameSignature(PartialMethodInfo other, StringComparer nameComparer) { return(nameComparer.Equals(this.Name, other.Name) && this.TypeParameterCount == other.TypeParameterCount && ParameterListComparer.Instance.Equals(this.Parameters, other.Parameters)); }
private void defineClassMethod(MethodDeclarationNode methodDeclaration, bool partial, TypeBuilder typeBuilder) { var name = context.getIdentifier(methodDeclaration.NameOffset, methodDeclaration.NameLength); if (name.equals("finalize") && methodDeclaration.Parameters.size() == 0) { context.addError(CompileErrorId.FinalizeMethodOverride, methodDeclaration); } if (methodDeclaration.IsPartial) { if (!partial) { context.addError(CompileErrorId.PartialMethodWithinPartialClass, methodDeclaration); } if (methodDeclaration.ReturnType != context.TypeSystem.VoidType) { context.addError(CompileErrorId.PartialMethodNotVoid, methodDeclaration); } } var methodBuilder = lookupMethod(typeBuilder, methodDeclaration.TypeParameters, methodDeclaration.Parameters, name); if (methodBuilder != null) { if (!methodDeclaration.IsPartial) { context.addError(CompileErrorId.AlreadyDefinedMethod, methodDeclaration, BytecodeHelper.getDisplayName(typeBuilder), name); return; } var partialInfo = partialTypes[typeBuilder.FullName]; if (!partialInfo.partialMethods.containsKey(methodBuilder)) { context.addError(CompileErrorId.AlreadyDefinedMethod, methodDeclaration, BytecodeHelper.getDisplayName(typeBuilder), name); } var partialMethodInfo = partialInfo.partialMethods[methodBuilder]; if (methodDeclaration.Body == null) { if (partialMethodInfo.definingPart != null) { context.addError(CompileErrorId.MultiplePartialDefiningDeclarations, methodDeclaration); } partialMethodInfo.definingPart = methodDeclaration; } else { if (partialMethodInfo.implementingPart != null) { context.addError(CompileErrorId.MultiplePartialImplementingDeclarations, methodDeclaration); } partialMethodInfo.implementingPart = methodDeclaration; } setPartialMethodModifiers(methodDeclaration, methodBuilder); setMethodConstraints(methodDeclaration.ConstraintsClauses, methodBuilder); methodDeclaration.addUserData(methodBuilder); } else { methodBuilder = typeBuilder.defineMethod(name); methodDeclaration.addUserData(methodBuilder); setTypeParameters(methodBuilder, methodDeclaration.TypeParameters, methodDeclaration); context.MemberResolver.enterMethod(methodBuilder); try { setMethodModifiers(methodDeclaration, methodBuilder); var returnType = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, methodDeclaration.ReturnType); methodBuilder.setReturnType(returnType); var i = 0; foreach (var parameter in methodDeclaration.Parameters) { var type = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, parameter.Type); var paramBuilder = methodBuilder.addParameter(type); paramBuilder.setName(context.getIdentifier(parameter.NameOffset, parameter.NameLength)); if (parameter.Modifier == ParameterModifier.Params) { if (i < methodDeclaration.Parameters.size() - 1) { context.addError(CompileErrorId.ParamsNotLast, parameter); } if (!type.IsArray) { context.addError(CompileErrorId.ParamsNotArray, parameter); } methodBuilder.setVarargs(true); } else if (parameter.Modifier == ParameterModifier.This) { if (!methodBuilder.IsStatic) { context.addError(CompileErrorId.ThisParameterNotStatic, parameter); } if (i > 0) { context.addError(CompileErrorId.ThisNotFirst, parameter); } methodBuilder.addAnnotation(context.getType("stab/lang/ExtensionMethod", parameter), false); } i++; } setMethodConstraints(methodDeclaration.ConstraintsClauses, methodBuilder); if (methodDeclaration.IsPartial) { var partialInfo = partialTypes[typeBuilder.getFullName()]; var partialMethodInfo = new PartialMethodInfo(); if (methodDeclaration.Body == null) { partialMethodInfo.definingPart = methodDeclaration; } else { partialMethodInfo.implementingPart = methodDeclaration; } partialInfo.partialMethods[methodBuilder] = partialMethodInfo; } } finally { context.MemberResolver.leaveMethod(); } } }