aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarl Heuer1998-04-08 19:07:45 +0000
committerKarl Heuer1998-04-08 19:07:45 +0000
commit35dd3c558f94c5988dbd5cc7fc16af0b66c33df7 (patch)
tree2ce17877480b992f8c6dbd850d1b6f84100438f9
parentc241bb9cbbd81b6327a511b7fc3e7cd63e432909 (diff)
downloademacs-35dd3c558f94c5988dbd5cc7fc16af0b66c33df7.tar.gz
emacs-35dd3c558f94c5988dbd5cc7fc16af0b66c33df7.zip
(jdb): Do proper analysis of classes defined in a Java
source. This removes the restriction of one class per file. (gud-jdb-package-of-file): Removed. Replaced with parsing routines. (gud-jdb-skip-whitespace): New function. (gud-jdb-skip-single-line-comment): New function. (gud-jdb-skip-traditional-or-documentation-comment): New function. (gud-jdb-skip-whitespace-and-comments): New function. (gud-jdb-skip-id-ish-thing): New function. (gud-jdb-skip-string-literal): New function. (gud-jdb-skip-character-literal): New function. (gud-jdb-skip-block): New function. (gud-jdb-analyze-source): New function. (gud-jdb-build-class-source-alist-for-file): New function. (gud-jdb-analysis-buffer): New variable. (gud-jdb-build-class-source-alist): Cleaner at the expense of new variable.
-rw-r--r--lisp/gud.el260
1 files changed, 227 insertions, 33 deletions
diff --git a/lisp/gud.el b/lisp/gud.el
index 47e111bcfe2..eb71dabd2de 100644
--- a/lisp/gud.el
+++ b/lisp/gud.el
@@ -1316,22 +1316,37 @@ and source-file directory for your debugger."
1316;; 1316;;
1317;; Type M-n to step over the current line and M-s to step into it. That, 1317;; Type M-n to step over the current line and M-s to step into it. That,
1318;; along with the JDB 'help' command should get you started. The 'quit' 1318;; along with the JDB 'help' command should get you started. The 'quit'
1319;; JDB command will get out out of the debugger. 1319;; JDB command will get out out of the debugger. There is some truly
1320;; pathetic JDB documentation available at:
1321;;
1322;; http://java.sun.com/products/jdk/1.1/debugging/
1320;; 1323;;
1321;; KNOWN PROBLEMS AND FIXME's: 1324;; KNOWN PROBLEMS AND FIXME's:
1322;; 1325;;
1323;; Each source file must contain one and only one class or interface 1326;; Not sure what happens with inner classes ... haven't tried them.
1324;; definition.
1325;; 1327;;
1326;; Does not grok UNICODE id's. Only ASCII id's are supported. 1328;; Does not grok UNICODE id's. Only ASCII id's are supported.
1327;; 1329;;
1328;; Loses when valid package statements are embedded in certain kinds of
1329;; comments and/or string literals, but this should be rare.
1330;;
1331;; You must not put whitespace between "-classpath" and the path to 1330;; You must not put whitespace between "-classpath" and the path to
1332;; search for java classes even though it is required when invoking jdb 1331;; search for java classes even though it is required when invoking jdb
1333;; from the command line. See gud-jdb-massage-args for details. 1332;; from the command line. See gud-jdb-massage-args for details.
1334;; 1333;;
1334;; If any of the source files in the directories listed in
1335;; gud-jdb-directories won't parse you'll have problems. Make sure
1336;; every file ending in ".java" in these directories parses without error.
1337;;
1338;; All the .java files in the directories in gud-jdb-directories are
1339;; syntactically analyzed each time gud jdb is invoked. It would be
1340;; nice to keep as much information as possible between runs. It would
1341;; be really nice to analyze the files only as neccessary (when the
1342;; source needs to be displayed.) I'm not sure to what extent the former
1343;; can be accomplished and I'm not sure the latter can be done at all
1344;; since I don't know of any general way to tell which .class files are
1345;; defined by which .java file without analyzing all the .java files.
1346;; If anyone knows why JavaSoft didn't put the source file names in
1347;; debuggable .class files please clue me in so I find something else
1348;; to be spiteful and bitter about.
1349;;
1335;; ====================================================================== 1350;; ======================================================================
1336;; gud jdb variables and functions 1351;; gud jdb variables and functions
1337 1352
@@ -1352,42 +1367,221 @@ The file names should be absolute, or relative to the current directory.")
1352(defun gud-jdb-build-source-files-list (path extn) 1367(defun gud-jdb-build-source-files-list (path extn)
1353 (apply 'nconc (mapcar (lambda (d) (directory-files d t extn nil)) path))) 1368 (apply 'nconc (mapcar (lambda (d) (directory-files d t extn nil)) path)))
1354 1369
1355;; Return the package (with trailing period) to which FILE belongs. 1370;; Move point past whitespace.
1356;; Returns "" if FILE is in the default package. BUF is the name of a 1371(defun gud-jdb-skip-whitespace ()
1357;; buffer into which FILE is read so that it can be searched in order 1372 (skip-chars-forward " \n\r\t\014"))
1358;; to determine it's package. As a consequence, the contents of BUF 1373
1359;; are erased by this function. 1374;; Move point past a "// <eol>" type of comment.
1360(defun gud-jdb-package-of-file (buf file) 1375(defun gud-jdb-skip-single-line-comment ()
1361 (set-buffer buf) 1376 (end-of-line))
1362 (insert-file-contents file nil nil nil t) 1377
1363 ;; FIXME: Java IDs are UNICODE strings - this code does not 1378;; Move point past a "/* */" or "/** */" type of comment.
1364 ;; do the right thing! 1379(defun gud-jdb-skip-traditional-or-documentation-comment ()
1365 ;; FIXME: Does not always ignore contents of comments or string literals. 1380 (forward-char 2)
1366 (if (re-search-forward 1381 (catch 'break
1367 "^[ \t]*package[ \t]+\\([a-zA-Z0-9$_\.]+\\)[ \t]*;" nil t) 1382 (while (not (eobp))
1368 (concat (match-string 1) ".") 1383 (if (eq (following-char) ?*)
1369 "")) 1384 (progn
1385 (forward-char)
1386 (if (not (eobp))
1387 (if (eq (following-char) ?/)
1388 (progn
1389 (forward-char)
1390 (throw 'break nil)))))
1391 (forward-char)))))
1392
1393;; Move point past any number of consecutive whitespace chars and/or comments.
1394(defun gud-jdb-skip-whitespace-and-comments ()
1395 (gud-jdb-skip-whitespace)
1396 (catch 'done
1397 (while t
1398 (cond
1399 ((looking-at "//")
1400 (gud-jdb-skip-single-line-comment)
1401 (gud-jdb-skip-whitespace))
1402 ((looking-at "/\\*")
1403 (gud-jdb-skip-traditional-or-documentation-comment)
1404 (gud-jdb-skip-whitespace))
1405 (t (throw 'done nil))))))
1406
1407;; Move point past things that are id-like. The intent is to skip regular
1408;; id's, such as class or interface names as well as package and interface
1409;; names.
1410(defun gud-jdb-skip-id-ish-thing ()
1411 (skip-chars-forward "^ /\n\r\t\014,;{"))
1412
1413;; Move point past a string literal.
1414(defun gud-jdb-skip-string-literal ()
1415 (forward-char)
1416 (while
1417 (progn
1418 (if (eq (following-char) ?\\)
1419 (forward-char 2))
1420 (not (eq (following-char) ?\042)))
1421 (forward-char))
1422 (forward-char))
1423
1424;; Move point past a character literal.
1425(defun gud-jdb-skip-character-literal ()
1426 (forward-char)
1427 (while
1428 (progn
1429 (if (eq (following-char) ?\\)
1430 (forward-char 2))
1431 (not (eq (following-char) ?\')))
1432 (forward-char))
1433 (forward-char))
1434
1435;; Move point past the following block. There may be (legal) cruft before
1436;; the block's opening brace. There must be a block or it's the end of life
1437;; in petticoat junction.
1438(defun gud-jdb-skip-block ()
1439
1440 ;; Find the begining of the block.
1441 (while
1442 (not (eq (following-char) ?{))
1443
1444 ;; Skip any constructs that can harbor literal block delimiter
1445 ;; characters and/or the delimiters for the constructs themselves.
1446 (cond
1447 ((looking-at "//")
1448 (gud-jdb-skip-single-line-comment))
1449 ((looking-at "/\\*")
1450 (gud-jdb-skip-traditional-or-documentation-comment))
1451 ((eq (following-char) ?\042)
1452 (gud-jdb-skip-string-literal))
1453 ((eq (following-char) ?\')
1454 (gud-jdb-skip-character-literal))
1455 (t (forward-char))))
1456
1457 ;; Now at the begining of the block.
1458 (forward-char)
1459
1460 ;; Skip over the body of the block as well as the final brace.
1461 (let ((open-level 1))
1462 (while (not (eq open-level 0))
1463 (cond
1464 ((looking-at "//")
1465 (gud-jdb-skip-single-line-comment))
1466 ((looking-at "/\\*")
1467 (gud-jdb-skip-traditional-or-documentation-comment))
1468 ((eq (following-char) ?\042)
1469 (gud-jdb-skip-string-literal))
1470 ((eq (following-char) ?\')
1471 (gud-jdb-skip-character-literal))
1472 ((eq (following-char) ?{)
1473 (setq open-level (+ open-level 1))
1474 (forward-char))
1475 ((eq (following-char) ?})
1476 (setq open-level (- open-level 1))
1477 (forward-char))
1478 (t (forward-char))))))
1479
1480;; Find the package and class definitions in Java source file FILE. Assumes
1481;; that FILE contains a legal Java program. BUF is a scratch buffer used
1482;; to hold the source during analysis.
1483(defun gud-jdb-analyze-source (buf file)
1484 (let ((l nil))
1485 (set-buffer buf)
1486 (insert-file-contents file nil nil nil t)
1487 (goto-char 0)
1488 (catch 'abort
1489 (let ((p ""))
1490 (while (progn
1491 (gud-jdb-skip-whitespace)
1492 (not (eobp)))
1493 (cond
1494
1495 ;; Any number of semi's following a block is legal. Move point
1496 ;; past them. Note that comments and whitespace may be
1497 ;; interspersed as well.
1498 ((eq (following-char) ?\073)
1499 (forward-char))
1500
1501 ;; Move point past a single line comment.
1502 ((looking-at "//")
1503 (gud-jdb-skip-single-line-comment))
1504
1505 ;; Move point past a traditional or documentation comment.
1506 ((looking-at "/\\*")
1507 (gud-jdb-skip-traditional-or-documentation-comment))
1508
1509 ;; Move point past a package statement, but save the PackageName.
1510 ((looking-at "package")
1511 (forward-char 7)
1512 (gud-jdb-skip-whitespace-and-comments)
1513 (let ((s (point)))
1514 (gud-jdb-skip-id-ish-thing)
1515 (setq p (concat (buffer-substring s (point)) "."))
1516 (gud-jdb-skip-whitespace-and-comments)
1517 (if (eq (following-char) ?\073)
1518 (forward-char))))
1519
1520 ;; Move point past an import statement.
1521 ((looking-at "import")
1522 (forward-char 6)
1523 (gud-jdb-skip-whitespace-and-comments)
1524 (gud-jdb-skip-id-ish-thing)
1525 (gud-jdb-skip-whitespace-and-comments)
1526 (if (eq (following-char) ?\073)
1527 (forward-char)))
1528
1529 ;; Move point past the various kinds of ClassModifiers.
1530 ((looking-at "public")
1531 (forward-char 6))
1532 ((looking-at "abstract")
1533 (forward-char 8))
1534 ((looking-at "final")
1535 (forward-char 5))
1536
1537 ;; Move point past a ClassDeclaraction, but save the class
1538 ;; Identifier.
1539 ((looking-at "class")
1540 (forward-char 5)
1541 (gud-jdb-skip-whitespace-and-comments)
1542 (let ((s (point)))
1543 (gud-jdb-skip-id-ish-thing)
1544 (setq
1545 l (nconc l (list (concat p (buffer-substring s (point)))))))
1546 (gud-jdb-skip-block))
1547
1548 ;; Move point past an interface statement.
1549 ((looking-at "interface")
1550 (forward-char 9)
1551 (gud-jdb-skip-block))
1552
1553 ;; Anything else means the input is invalid.
1554 (t
1555 (message (format "Error parsing file %s." file))
1556 (throw 'abort nil))))))
1557 l))
1558
1559(defun gud-jdb-build-class-source-alist-for-file (file)
1560 (mapcar
1561 (lambda (c)
1562 (cons c file))
1563 (gud-jdb-analyze-source gud-jdb-analysis-buffer file)))
1370 1564
1371;; Association list of fully qualified class names (package + class name) and 1565;; Association list of fully qualified class names (package + class name) and
1372;; their source files. 1566;; their source files.
1373(defvar gud-jdb-class-source-alist nil) 1567(defvar gud-jdb-class-source-alist nil)
1374 1568
1569;; This is used to hold a source file during analysis.
1570(defvar gud-jdb-analysis-buffer nil)
1571
1375;; Return an alist of fully qualified classes and the source files 1572;; Return an alist of fully qualified classes and the source files
1376;; holding their definitions. SOURCES holds a list of all the source 1573;; holding their definitions. SOURCES holds a list of all the source
1377;; files to examine. 1574;; files to examine.
1378(defun gud-jdb-build-class-source-alist (sources) 1575(defun gud-jdb-build-class-source-alist (sources)
1379 (let ((tmpbuf (get-buffer-create "*gud-jdb-scratch*"))) 1576 (setq gud-jdb-analysis-buffer (get-buffer-create "*gud-jdb-scratch*"))
1380 (prog1 1577 (prog1
1381 (mapcar 1578 (apply
1382 (lambda (s) 1579 'nconc
1383 (cons 1580 (mapcar
1384 (concat 1581 'gud-jdb-build-class-source-alist-for-file
1385 (gud-jdb-package-of-file tmpbuf s) 1582 sources))
1386 (file-name-sans-versions 1583 (kill-buffer gud-jdb-analysis-buffer)
1387 (file-name-sans-extension 1584 (setq gud-jdb-analysis-buffer nil)))
1388 (file-name-nondirectory s))))
1389 s)) sources)
1390 (kill-buffer tmpbuf))))
1391 1585
1392;; Change what was given in the minibuffer to something that can be used to 1586;; Change what was given in the minibuffer to something that can be used to
1393;; invoke the debugger. 1587;; invoke the debugger.