@@ -269,6 +269,109 @@ def _handler(params):
269269 ), f"Expected diagnostics for { cell_uri !r} , got: { received } "
270270
271271
272+ def test_notebook_did_change_new_cell_kind_filter ():
273+ """Diagnostics are only published for newly added code cells, not markdown cells.
274+
275+ When a notebook change adds both a code cell and a markdown cell via
276+ structure.did_open, only the code cell should receive diagnostics.
277+ """
278+ nb_path = str (constants .TEST_DATA / "sample1" / "sample.ipynb" )
279+ nb_uri = _make_notebook_uri (nb_path )
280+ code_cell_id = "cell_code"
281+ md_cell_id = "cell_md"
282+ code_cell_uri = _make_cell_uri (nb_path , code_cell_id )
283+ md_cell_uri = _make_cell_uri (nb_path , md_cell_id )
284+
285+ with session .LspSession () as ls_session :
286+ ls_session .initialize (defaults .VSCODE_DEFAULT_INITIALIZE )
287+
288+ # Open an initially empty notebook
289+ ls_session .notify_notebook_did_open (
290+ {
291+ "notebookDocument" : {
292+ "uri" : nb_uri ,
293+ "notebookType" : "jupyter-notebook" ,
294+ "version" : 1 ,
295+ "metadata" : {},
296+ "cells" : [],
297+ },
298+ "cellTextDocuments" : [],
299+ }
300+ )
301+
302+ received = []
303+ done = Event ()
304+
305+ def _handler (params ):
306+ received .append (params )
307+ done .set ()
308+
309+ ls_session .set_notification_callback (session .PUBLISH_DIAGNOSTICS , _handler )
310+
311+ # Add both a code cell (kind=2) and a markdown cell (kind=1) at once
312+ ls_session .notify_notebook_did_change (
313+ {
314+ "notebookDocument" : {
315+ "uri" : nb_uri ,
316+ "version" : 2 ,
317+ },
318+ "change" : {
319+ "metadata" : None ,
320+ "cells" : {
321+ "structure" : {
322+ "array" : {
323+ "start" : 0 ,
324+ "deleteCount" : 0 ,
325+ "cells" : [
326+ {
327+ "kind" : 2 , # Code
328+ "document" : code_cell_uri ,
329+ "metadata" : {},
330+ "executionSummary" : None ,
331+ },
332+ {
333+ "kind" : 1 , # Markdown
334+ "document" : md_cell_uri ,
335+ "metadata" : {},
336+ "executionSummary" : None ,
337+ },
338+ ],
339+ },
340+ "didOpen" : [
341+ {
342+ "uri" : code_cell_uri ,
343+ "languageId" : "python" ,
344+ "version" : 1 ,
345+ "text" : "x = 1\n " ,
346+ },
347+ {
348+ "uri" : md_cell_uri ,
349+ "languageId" : "markdown" ,
350+ "version" : 1 ,
351+ "text" : "# heading\n " ,
352+ },
353+ ],
354+ "didClose" : None ,
355+ },
356+ "data" : None ,
357+ "textContent" : None ,
358+ },
359+ },
360+ }
361+ )
362+
363+ done .wait (TIMEOUT )
364+
365+ # The code cell should receive diagnostics; the markdown cell must not.
366+ uris_with_diagnostics = {r .get ("uri" ) for r in received }
367+ assert code_cell_uri in uris_with_diagnostics , (
368+ f"Expected diagnostics for code cell { code_cell_uri !r} , got: { received } "
369+ )
370+ assert md_cell_uri not in uris_with_diagnostics , (
371+ f"Markdown cell { md_cell_uri !r} should not receive diagnostics, got: { received } "
372+ )
373+
374+
272375def test_notebook_did_close ():
273376 """Diagnostics are cleared for all cells when a notebook is closed.
274377
0 commit comments