private void addMethods(ComboType combo, List<AbstractMsType> methods)
			throws CancelledException {

		if (methods.isEmpty()) {
			return;
		}
		CppCompositeType cppCompositeType = combo.ct();
		SymbolPath classSymbolPath = cppCompositeType.getSymbolPath();
		Access defaultAccess = cppCompositeType.getDefaultAccess();

		for (AbstractMsType methodType : methods) {
			applicator.checkCancelled();
			if (methodType instanceof AbstractOneMethodMsType oneMethodType) {
				String name = oneMethodType.getName();
				ClassFieldMsAttributes attributes = oneMethodType.getAttributes();
				AbstractMsType t =
					applicator.getPdb().getTypeRecord(oneMethodType.getProcedureTypeRecordNumber());
				int adjuster = 0;
				if (t instanceof AbstractMemberFunctionMsType memberFunc) {
					adjuster = memberFunc.getThisAdjuster();
				}
				Long offset = oneMethodType.getOffsetInVFTableIfIntroVirtual();
				RecordNumber procedureTypeRn = oneMethodType.getProcedureTypeRecordNumber();
				DataType dt = applicator.getDataType(procedureTypeRn);
				if (!(dt instanceof FunctionDefinition def)) {
					Msg.warn(this,
						"MemberFunction expected, but found: " + dt.getClass().getSimpleName());
					// Put something in its place?  Or abort the whole class?
					continue;
				}
				SymbolPath methodSymbolPath =
					classSymbolPath.append(new SymbolPath(name)).replaceInvalidChars();
				ClassFieldAttributes atts = ClassFieldAttributes.convert(attributes, defaultAccess);
				if (atts.getProperty() == Property.VIRTUAL) {
					cppCompositeType.addVirtualMethod(adjuster, offset.intValue(), methodSymbolPath,
						def);
				}
			}
			else if (methodType instanceof AbstractOverloadedMethodMsType overloadedMethodType) {
				String name = overloadedMethodType.getName();
				RecordNumber methodsListRn = overloadedMethodType.getTypeMethodListRecordNumber();
				AbstractMsType methodsListTry = applicator.getTypeRecord(methodsListRn);
				if (methodsListTry instanceof AbstractMethodListMsType methodsListType) {
					SymbolPath methodSymbolPath =
						classSymbolPath.append(new SymbolPath(name)).replaceInvalidChars();
					List<AbstractMethodRecordMs> recordList = methodsListType.getList();
					for (AbstractMethodRecordMs methodRecord : recordList) {
						applicator.checkCancelled();
						Long offset = methodRecord.getOptionalOffset();
						RecordNumber procedureTypeRn = methodRecord.getProcedureTypeRecordNumber();
						ClassFieldMsAttributes attributes = methodRecord.getAttributes();
						AbstractMsType t = applicator.getPdb().getTypeRecord(procedureTypeRn);
						int adjuster = 0;
						if (t instanceof AbstractMemberFunctionMsType memberFunc) {
							adjuster = memberFunc.getThisAdjuster();
						}
						DataType dt = applicator.getDataType(procedureTypeRn);
						if (!(dt instanceof FunctionDefinition def)) {
							Msg.warn(this,
								"MemberFunction expected, but found: " +
									dt.getClass().getSimpleName());
							// Put something in its place?  Or abort the whole class?
							continue;
						}
						ClassFieldAttributes atts =
							ClassFieldAttributes.convert(attributes, defaultAccess);
						if (atts.getProperty() == Property.VIRTUAL) {
							cppCompositeType.addVirtualMethod(adjuster, offset.intValue(),
								methodSymbolPath, def);
						}
					}
				}
				else {
					Msg.warn(this, "Unexexpected method list type: " +
						methodsListTry.getClass().getSimpleName());
				}
			}
			else {
				Msg.warn(this,
					"Unexexpected method type: " + methodType.getClass().getSimpleName());
			}
		}
	}
Constructor for composite type applier, for transforming a composite into a Ghidra DataType
@param applicator {@link DefaultPdbApplicator} for which this class is working
Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java