diff --git a/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb b/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb
index 0f53748cf0..8bc0708aec 100644
--- a/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb
+++ b/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb
@@ -14,6 +14,12 @@ class RuboCopDiagnostic
           fatal: Constant::DiagnosticSeverity::ERROR,
         }.freeze #: Hash[Symbol, Integer]
 
+        # Cops where adding a `rubocop:disable` inline comment would itself resolve the offense,
+        # causing Lint/RedundantCopDisableDirective to flag the disable as unnecessary.
+        SELF_RESOLVING_DISABLE_COPS = Set.new([
+          "Layout/EmptyComment",
+        ]).freeze #: Set[String]
+
         ENHANCED_DOC_URL = begin
           gem("rubocop", ">= 1.64.0")
           true
@@ -35,7 +41,7 @@ def to_lsp_code_actions
           code_actions = []
 
           code_actions << autocorrect_action if correctable?
-          code_actions << disable_line_action
+          code_actions << disable_line_action unless SELF_RESOLVING_DISABLE_COPS.include?(@offense.cop_name)
 
           code_actions
         end
diff --git a/test/requests/code_actions_formatting_test.rb b/test/requests/code_actions_formatting_test.rb
index 63ac0afe65..2e6a375147 100644
--- a/test/requests/code_actions_formatting_test.rb
+++ b/test/requests/code_actions_formatting_test.rb
@@ -39,6 +39,15 @@ def test_disable_line__continuation
     assert_disable_line("continuation", "Layout/SpaceAroundOperators")
   end
 
+  def test_no_disable_line_for_self_resolving_cops
+    source = <<~RUBY
+      #
+      def foo; end
+    RUBY
+
+    assert_no_disable_action(source, "Layout/EmptyComment")
+  end
+
   private
 
   def assert_disable_line(fixture, cop_name)
@@ -49,6 +58,15 @@ def assert_disable_line(fixture, cop_name)
     )
   end
 
+  #: (String source, String diagnostic_code) -> void
+  def assert_no_disable_action(source, diagnostic_code)
+    _document, _diagnostic, result = setup_code_action_context(source, diagnostic_code)
+
+    disable_action = find_code_action_by_title(result, "Disable #{diagnostic_code} for this line")
+
+    assert_nil(disable_action, "Should not offer disable action for self-resolving cops")
+  end
+
   def assert_fixtures_match(name, diagnostic_code, code_action_title)
     actual, expected = load_expectation(name)
     assert_corrects_to_expected(
@@ -59,8 +77,36 @@ def assert_fixtures_match(name, diagnostic_code, code_action_title)
     )
   end
 
+  #: (String name) -> [String, String]
+  def load_expectation(name)
+    source = File.read(File.join(TEST_FIXTURES_DIR, "#{name}.rb"))
+    expected = File.read(File.join(TEST_EXP_DIR, "#{name}.exp.rb"))
+    [source, expected]
+  end
+
   #: (String diagnostic_code, String code_action_title, String source, String expected) -> untyped
   def assert_corrects_to_expected(diagnostic_code, code_action_title, source, expected)
+    document, _diagnostic, result = setup_code_action_context(source, diagnostic_code)
+
+    selected_action = find_code_action_by_title(result, code_action_title) #: as !nil
+
+    assert(selected_action, "Expected to find code action with title '#{code_action_title}'")
+
+    # transform edits from lsp to the format RubyLsp::Document wants them
+    # this doesn't work with multiple edits if any edits add lines
+    edits = selected_action.dig(:edit, :documentChanges).flat_map do |doc_change|
+      doc_change[:edits].map do |edit|
+        { range: edit[:range], text: edit[:newText] }
+      end
+    end
+
+    document.push_edits(edits, version: 2)
+
+    assert_equal(document.source, expected)
+  end
+
+  #: (String source, String diagnostic_code) -> [RubyLsp::RubyDocument, LanguageServer::Protocol::Interface::Diagnostic, Array[LanguageServer::Protocol::Interface::CodeAction]?]
+  def setup_code_action_context(source, diagnostic_code)
     global_state = RubyLsp::GlobalState.new
     global_state.apply_options({
       initializationOptions: { linters: ["rubocop_internal"] },
@@ -78,43 +124,26 @@ def assert_corrects_to_expected(diagnostic_code, code_action_title, source, expe
     )
 
     diagnostics = RubyLsp::Requests::Diagnostics.new(global_state, document).perform
-    # The source of the returned attributes may be RuboCop or Prism. Prism diagnostics don't have a code.
     rubocop_diagnostics = diagnostics&.select { _1.attributes[:source] == "RuboCop" }
-    diagnostic = rubocop_diagnostics&.find { |d| d.attributes[:code] && (d.code == diagnostic_code) } #: as !nil
+    diagnostic = rubocop_diagnostics&.find { |d| d.attributes[:code] == diagnostic_code } #: as !nil
+
+    assert(diagnostic, "Expected #{diagnostic_code} diagnostic to be present")
+
     range = diagnostic.range.to_hash.transform_values(&:to_hash)
     result = RubyLsp::Requests::CodeActions.new(document, range, {
       diagnostics: [JSON.parse(diagnostic.to_json, symbolize_names: true)],
     }).perform
 
+    [document, diagnostic, result]
+  end
+
+  #: (Array[LanguageServer::Protocol::Interface::CodeAction]?, String) -> Hash[Symbol, untyped]?
+  def find_code_action_by_title(result, title)
     # CodeActions#run returns Array<CodeAction, Hash>. We're interested in the
     # hashes here, so cast to untyped and only look at those.
     untyped_result = result #: untyped
-    selected_action = untyped_result.find do |ca|
-      ca.respond_to?(:[]) && ca[:title] == code_action_title
-    end
-
-    # transform edits from lsp to the format RubyLsp::Document wants them
-    # this doesn't work with multiple edits if any edits add lines
-    edits = selected_action.dig(:edit, :documentChanges).flat_map do |doc_change|
-      doc_change[:edits].map do |edit|
-        { range: edit[:range], text: edit[:newText] }
-      end
+    untyped_result.find do |ca|
+      ca.respond_to?(:[]) && ca[:title] == title
     end
-
-    document.push_edits(edits, version: 2)
-    # if document.source != expected
-    #   $stderr.puts("\n### #{@NAME.sub("test_", "")} ###")
-    #   $stderr.puts("#### ACTUAL ####\n#{document.source}\n")
-    #   $stderr.puts("#### EXPECTED ####\n#{expected}\n")
-    # end
-
-    assert_equal(document.source, expected)
-  end
-
-  #: (String name) -> [String, String]
-  def load_expectation(name)
-    source = File.read(File.join(TEST_FIXTURES_DIR, "#{name}.rb"))
-    expected = File.read(File.join(TEST_EXP_DIR, "#{name}.exp.rb"))
-    [source, expected]
   end
 end
