public void createActions() {

		// Provides the icon in the toolbar that makes a selection based on what you have in the table.
		DockingAction selectionAction =
			new MakeProgramSelectionAction(plugin, filterTable.getTable());

		DockingAction clearTaintMarksAction =
			new DockingAction("Clear All Taint Marks", plugin.getName()) {

				@Override
				public void actionPerformed(ActionContext context) {
					// empty out the marker sets.
					plugin.getTaintState().clearMarkers();
					// clear the markers in the decompiler window.
					plugin.clearIcons();

					// load empty marker set and then reload the table.
					model.getDataFrame().loadData();
					model.reload();
				}

				@Override
				public boolean isEnabledForContext(ActionContext context) {
					return plugin.getTaintState().hasMarks();
				}
			};

		clearTaintMarksAction.setToolBarData(new ToolBarData(clearTaintTagsIcon));

		DockingAction queryAction =
			new DockingAction("Execute Source-Sink Query", plugin.getName()) {
				@Override
				public void actionPerformed(ActionContext context) {
					Msg.info(this, "Execute Source-Sink Query from Taint Labels Table");

					Program currentProgram = plugin.getCurrentProgram();
					if (currentProgram == null)
						return;

					TaintState state = plugin.getTaintState();

					Task queryTask = new Task("Source-Sink Query Task", true, true, true, true) {
						@Override
						public void run(TaskMonitor monitor) {
							state.setCancellation(false);
							monitor.initialize(program.getFunctionManager().getFunctionCount());
							// query index NOT the default query; use table data.
							boolean successful =
								state.queryIndex(currentProgram, tool, QueryType.SRCSINK);
							state.setCancellation(!successful || monitor.isCancelled());
							monitor.clearCancelled();
						}
					};

					// This task will block -- see params above.
					// The blocking is necessary because of the table provider we create below.
					// It is problematic to do GUI stuff in the thread.
					// We still get a progress bar and option to cancel.
					// 1. Query Index.
					tool.execute(queryTask);

					if (!state.wasCancelled()) {
						// 2. Show Table.
						SarifService sarifService = plugin.getSarifService();
						sarifService.getController()
								.setDefaultGraphHander(SarifTaintGraphRunHandler.class);
						sarifService.showSarif("query", state.getData());

						// 3. Set Initial Highlights
						plugin.consoleMessage("executing query...");
						TaintProvider provider = plugin.getProvider();
						provider.setTaint();
						plugin.consoleMessage("query complete");
						state.setCancellation(false);

					}
					else {
						plugin.consoleMessage("Source-Sink query was cancelled.");
					}
				}

				@Override
				public boolean isEnabledForContext(ActionContext context) {
					// TODO make this smarter.
					return true;
				}
			};

		queryAction.setToolBarData(new ToolBarData(executeTaintQueryIcon));

		addLocalAction(selectionAction);
		addLocalAction(clearTaintMarksAction);
		addLocalAction(queryAction);
	}
Add actions to various table features.
Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintLabelsTableProvider.java