@SuppressWarnings({"unchecked", "DataFlowIssue"})
	private <I extends Info, P extends PathNode<?>> void visitDirtyItems(@Nonnull Workspace workspace,
	                                                                     @Nonnull WorkspaceResource resource,
	                                                                     @Nonnull Bundle<I> bundle,
	                                                                     @Nonnull PatchConsumer<P, I> consumer) throws Throwable {
		BundlePathNode bundlePath = PathNodes.bundlePath(workspace, resource, bundle);
		Set<String> dirtyKeys = bundle.getDirtyKeys();
		for (String dirtyKey : dirtyKeys) {
			Stack<I> history = bundle.getHistory(dirtyKey);
			I current = history.peek();
			I oldest = history.elementAt(0);
			int lastDirSeparator = dirtyKey.lastIndexOf('/');
			String directoryName = lastDirSeparator >= 0 ? dirtyKey.substring(0, lastDirSeparator) : null;
			DirectoryPathNode directoryPath = bundlePath.child(directoryName);
			if (current instanceof ClassInfo currentClass) {
				ClassPathNode classPath = directoryPath.child(currentClass);
				consumer.accept((P) classPath, oldest, current);
			} else if (current instanceof FileInfo currentFile) {
				FilePathNode filePath = directoryPath.child(currentFile);
				consumer.accept((P) filePath, oldest, current);
			}
		}
	}
Creates a patch which models all changes in the given workspace.

@param workspace
		Workspace to generate a patch for.

@return Patch modeling all changes made in the workspace.

@throws PatchGenerationException
		When the patch couldn't be made for any reason.
recaf-core/src/main/java/software/coley/recaf/services/workspace/patch/PatchProvider.java