private void setNestedClassModifiers(ClassDeclarationNode classDeclaration, TypeBuilder typeBuilder) {
     foreach (var modifier in classDeclaration.Modifiers) {
         switch (modifier) {
         case Public:
             if (typeBuilder.IsNestedPrivate || typeBuilder.IsNestedProtected) {
                 context.addError(CompileErrorId.PublicProtectedPrivate, classDeclaration);
             } else {
                 typeBuilder.setPublic(true);
                 typeBuilder.setNestedPublic(true);
             }
             break;
             
         case Protected:
             if (typeBuilder.IsNestedPrivate || typeBuilder.IsNestedPublic) {
                 context.addError(CompileErrorId.PublicProtectedPrivate, classDeclaration);
             } else {
                 typeBuilder.setNestedProtected(true);
             }
             break;
             
         case Private:
             if (typeBuilder.IsNestedProtected || typeBuilder.IsNestedPublic) {
                 context.addError(CompileErrorId.PublicProtectedPrivate, classDeclaration);
             } else {
                 typeBuilder.setNestedPrivate(true);
             }
             break;
             
         case Final:
         case Static:
             if (typeBuilder.IsAbstract || typeBuilder.IsFinal) {
                 context.addError(CompileErrorId.FinalAbstractStaticClass, classDeclaration);
             } else {
                 typeBuilder.setFinal(true);
                 typeBuilder.setNestedFinal(true);
             }
             break;
             
         case Abstract:
             if (typeBuilder.IsFinal) {
                 context.addError(CompileErrorId.FinalAbstractStaticClass, classDeclaration);
             } else {
                 typeBuilder.setAbstract(true);
                 typeBuilder.setNestedAbstract(true);
             }
             break;
             
         default:
             context.addError(CompileErrorId.UnexpectedModifier, classDeclaration, modifier.toString().toLowerCase());
             break;
         }
     }
 }
        private void setClassBaseTypes(ClassDeclarationNode classDeclaration) {
            var typeBuilder = classDeclaration.getUserData(typeof(TypeBuilder));
            context.MemberResolver.enterType(typeBuilder);
            try {
                var first = true;
                foreach (var typeReference in classDeclaration.ClassBase) {
                    var type = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, typeReference);
                    if (first) {
                        first = false;
                        if (type.IsInterface) {
                            typeBuilder.addInterface(type);
                        } else {
                            if (type.IsGenericParameter) {
                                context.addError(CompileErrorId.DeriveFromTypeVariable, typeReference, BytecodeHelper.getDisplayName(type));
                                continue;
                            }
                            if (typeBuilder.BaseType != null && typeBuilder.BaseType != type) {
                                context.addError(CompileErrorId.DifferentPartialBaseClass,
                                    typeReference, BytecodeHelper.getDisplayName(typeBuilder));
                                continue;
                            }
                            if (type.IsFinal) {
                                context.addError(CompileErrorId.FinalBaseClass, typeReference,
                                    BytecodeHelper.getDisplayName(typeBuilder), BytecodeHelper.getDisplayName(type));
                                continue;
                            }
                            if ((typeBuilder.IsPublic && !type.IsPublic) ||
                            	(!typeBuilder.IsNestedPrivate && type.IsNestedPrivate)) {
                                context.addError(CompileErrorId.InconsistentBaseTypeAccessibility, typeReference,
                                    BytecodeHelper.getDisplayName(typeBuilder), BytecodeHelper.getDisplayName(type));
                            }
                            typeBuilder.setBaseType(type);
                        }
                    } else {
                        if (!type.IsInterface) {
							if (typeBuilder.BaseType != null) {
								context.addError(CompileErrorId.MultipleBaseClass, typeReference,
									BytecodeHelper.getDisplayName(typeBuilder),
									BytecodeHelper.getDisplayName(type),
									BytecodeHelper.getDisplayName(typeBuilder.BaseType));
							} else {
								context.addError(CompileErrorId.BaseClassBeforeInterfaces, typeReference,
									BytecodeHelper.getDisplayName(type));
							}
                        }
                        typeBuilder.addInterface(type);
                    }
                }
                if (typeBuilder.BaseType == null) {
                    if (classDeclaration.IsEnum) {
                        typeBuilder.setEnum(true);
                        var enumType = context.TypeSystem.getType("java/lang/Enum");
                        typeBuilder.setBaseType(context.TypeSystem.getGenericType(enumType, Collections.singletonList<TypeInfo>(typeBuilder)));
                    } else {
                        typeBuilder.setBaseType(context.TypeSystem.ObjectType);
                    }
                }
                
                foreach (var member in classDeclaration.Members) {
                    switch (member.TypeMemberKind) {
                    case Class:
                        setClassBaseTypes((ClassDeclarationNode)member);
                        break;
                    case Interface:
                        setInterfaceBaseTypes((InterfaceDeclarationNode)member);
                        break;
                    case Delegate:
                        setDelegateBaseTypes((DelegateDeclarationNode)member);
                        break;
                    case Constructor:
                    case Destructor:
                    case EnumConstant:
                    case Field:
                    case Indexer:
                    case Method:
                    case Property:
                        break;
                    default:
                        throw new Exception("Internal error: unhandled member kind: " + member.TypeMemberKind);
                    }
                }

            } finally {
                context.MemberResolver.leaveType();
            }
        }
 private void defineNestedClass(TypeBuilder declaringClass, ClassDeclarationNode classDeclaration) {
     var shortName = context.getIdentifier(classDeclaration.NameOffset, classDeclaration.NameLength);
     var className = declaringClass.FullName + '$' + shortName;
     TypeBuilder typeBuilder = null;
     if (classDeclaration.IsPartial) {
         var partialTypeInfo = this.partialTypes[className];
         if (partialTypeInfo != null) {
             setNestedClassModifiers(classDeclaration, partialTypeInfo.typeBuilder);
             typeBuilder = partialTypeInfo.typeBuilder;
         }
     }
     if (typeBuilder == null) {
         typeBuilder = defineNestedType(declaringClass, className, shortName, classDeclaration);
         setNestedClassModifiers(classDeclaration, typeBuilder);
         if (classDeclaration.IsPartial) {
             this.partialTypes[className] = new PartialTypeInfo(typeBuilder);
         }
     }
     setTypeParameters(typeBuilder, classDeclaration.TypeParameters, classDeclaration);
     classDeclaration.addUserData(typeBuilder);
     typeBuilder.addUserData(classDeclaration);
     typeBuilder.setSuper(true);
     typeBuilder.setNestedStatic(true);
     defineNestedTypes(typeBuilder, classDeclaration);
 }
 private void defineNestedTypes(TypeBuilder declaringClass, ClassDeclarationNode classDeclaration) {
     foreach (var member in classDeclaration.Members) {
         switch (member.TypeMemberKind) {
         case Class:
             defineNestedClass(declaringClass, (ClassDeclarationNode)member);
             break;
         case Interface:
             defineNestedInterface(declaringClass, (InterfaceDeclarationNode)member);
             break;
         case Delegate:
             defineNestedDelegate(declaringClass, (DelegateDeclarationNode)member);
             break;
         case Constructor:
         case Destructor:
         case EnumConstant:
         case Field:
         case Indexer:
         case Method:
         case Property:
             break;
         default:
             throw new Exception("Internal error: unhandled member kind: " + member.TypeMemberKind);
         }
     }
 }
 private void defineClass(String packageName, ClassDeclarationNode classDeclaration) {
     var className = getTypeName(packageName, classDeclaration.NameOffset, classDeclaration.NameLength);
     TypeBuilder typeBuilder = null;
     if (classDeclaration.IsPartial) {
         var partialTypeInfo = this.partialTypes[className];
         if (partialTypeInfo != null) {
             setClassModifiers(classDeclaration, partialTypeInfo.typeBuilder);
             typeBuilder = partialTypeInfo.typeBuilder;
         }
     }
     if (typeBuilder == null) {
         typeBuilder = defineType(className, classDeclaration);
         setClassModifiers(classDeclaration, typeBuilder);
         if (classDeclaration.IsPartial) {
             this.partialTypes[className] = new PartialTypeInfo(typeBuilder);
         }
     }
     setTypeParameters(typeBuilder, classDeclaration.TypeParameters, classDeclaration);
     classDeclaration.addUserData(typeBuilder);
     typeBuilder.addUserData(classDeclaration);
     typeBuilder.setSuper(true);
     defineNestedTypes(typeBuilder, classDeclaration);
 }
 private void defineClassMembers(ClassDeclarationNode classDeclaration) {
     var typeBuilder = classDeclaration.getUserData(typeof(TypeBuilder));
     context.CurrentType = typeBuilder;
     context.MemberResolver.enterType(typeBuilder);
     try {
         setTypeConstraints(classDeclaration.ConstraintsClauses, typeBuilder);
         if (typeBuilder.IsEnum) {
             var fieldBuilder = typeBuilder.defineField("ENUM$VALUES", typeBuilder.ArrayType);
             fieldBuilder.setPrivate(true);
             fieldBuilder.setFinal(true);
             fieldBuilder.setStatic(true);
             
             var methodBuilder = typeBuilder.defineMethod("valueOf");
             methodBuilder.setPublic(true);
             methodBuilder.setStatic(true);
             methodBuilder.setReturnType(typeBuilder);
             var param = methodBuilder.addParameter(context.TypeSystem.StringType);
             param.setName("str");
             
             methodBuilder = typeBuilder.defineMethod("values");
             methodBuilder.setPublic(true);
             methodBuilder.setStatic(true);
             methodBuilder.setReturnType(typeBuilder.ArrayType);
         }
         
         foreach (var member in classDeclaration.Members) {
             switch (member.TypeMemberKind) {
             case Class:
                 defineClassMembers((ClassDeclarationNode)member);
                 break;
             case Interface:
                 defineInterfaceMembers((InterfaceDeclarationNode)member);
                 break;
             case Delegate:
                 defineDelegateMembers((DelegateDeclarationNode)member);
                 break;
             case Method:
                 defineClassMethod((MethodDeclarationNode)member, classDeclaration.IsPartial, typeBuilder);
                 break;
             case Field:
                 defineClassField((FieldDeclarationNode)member, typeBuilder);
                 break;
             case EnumConstant:
                 defineEnumConstant((EnumConstantDeclarationNode)member, typeBuilder);
                 break;
             case Indexer:
                 defineClassIndexer((IndexerDeclarationNode)member, typeBuilder);
                 break;
             case Property:
                 defineClassProperty((PropertyDeclarationNode)member, typeBuilder);
                 break;
             case Constructor:
                 defineClassConstructor((ConstructorDeclarationNode)member, typeBuilder);
                 break;
             case Destructor:
                 defineClassDestructor((DestructorDeclarationNode)member, typeBuilder);
                 break;
             default:
                 throw new Exception("Internal error: unhandled member kind: " + member.TypeMemberKind);
             }
             context.CurrentType = typeBuilder;
         }
     } finally {
         context.MemberResolver.leaveType();
     }
 }
		public void enterClass(ClassDeclarationNode declaration) {
			typeInfos.add(declaration.getUserData(typeof(TypeInfo)));
		}
 private ClassDeclarationNode parseClass(List<AnnotationSectionNode> annotations, EnumSet<Modifier> modifiers, bool isEnum,
         bool partial, int startPosition) {
     if (!isIdentifier(lexicalUnit)) {
         throw error(ParseErrorId.IdentifierExpected);
     }
     var result = new ClassDeclarationNode { IsEnum = isEnum, IsPartial = partial,
             NameOffset = scanner.StartPosition, NameLength = getLexicalUnitLength(), StartPosition = startPosition };
     if (docCommentEndPosition > 0) {
         result.DocumentationOffset = docCommentStartPosition;
         result.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
         docCommentEndPosition = 0;
     }
     setScannerState(result);
     result.Modifiers.addAll(modifiers);
     result.Annotations.addAll(annotations);
     nextLexicalUnit(true);
     if (!isEnum) {
         parseTypeParameters(result.TypeParameters);
     }
     parseClassBase(result.ClassBase);
     if (!isEnum) {
         parseTypeParameterConstraintsClauses(result.ConstraintsClauses);
     }
     if (lexicalUnit != LexicalUnit.OpenBrace) {
         throw error(ParseErrorId.OpenBraceExpected);
     }
     result.EndPosition = parseClassBody(annotations, modifiers, isEnum, result.Members);
     if (lexicalUnit == LexicalUnit.SemiColon) {
         nextLexicalUnit(false);
     }
     return result;
 }
		private void print(ClassDeclarationNode classDeclaration, int indent, StringBuilder sb) {
			var indentText = buildIndentText(indent);
			foreach (var attr in classDeclaration.Annotations) {
				print(attr, true, sb);
			}
			sb.append(indentText);
			print(classDeclaration.Modifiers, sb);
			if (classDeclaration.IsEnum) {
				sb.append("enum ");
			} else {
				sb.append("class ");
			}
			sb.append(new String(text, classDeclaration.NameOffset, classDeclaration.NameLength));
			print(classDeclaration.TypeParameters, sb);
			if (classDeclaration.ClassBase.size() > 0) {
				sb.append(" : ");
				bool first = true;
				foreach (var t in classDeclaration.ClassBase) {
					if (first) {
						first = false;
					} else {
						sb.append(", ");
					}
					print(t, sb);
				}
			}
			print(classDeclaration.ConstraintsClauses, indentText, sb);
			sb.append(" {\r\n");
			print(classDeclaration.Members, indent, sb);
			sb.append(indentText);
			sb.append("}\r\n");
		}