--- /dev/null
+before_install:
+ - wget http://frank.kank.net/travissbcl/style-checker/ef9a5c7/$(git rev-parse HEAD)/travissbcl
+ - chmod +x travissbcl
+
+script:
+ - ./travissbcl --script bin/travis.lisp
--- /dev/null
+#!/bin/bash -e
+
+mkdir -p tmp/sbcl
+
+cwd=$PWD
+( cd tmp &&
+ tar jxf ../deps/tarpit/sbcl-1.2.6-x86-64-linux-binary.tar.bz2 &&
+ cd sbcl-1.2.6-x86-64-linux/ &&
+ SBCL_HOME="" INSTALL_ROOT=$cwd/tmp/sbcl/ bash install.sh )
+
+mkdir -p tmp/deps/
+
+( cd tmp/deps &&
+ tar zxf ../../deps/tarpit/cl-ppcre.tar.gz &&
+ ln -s cl-ppcre-2.0.10/cl-ppcre.asd .
+)
+
+
+SBCL_HOME="" tmp/sbcl/bin/sbcl --core tmp/sbcl/lib/sbcl/sbcl.core --no-sysinit --no-userinit \
+ --eval "(require 'asdf)" \
+ --eval '(setf asdf:*central-registry* (list #p"tmp/deps/"))' \
+ --eval "(asdf:load-system :cl-ppcre)" \
+ --eval "(asdf:clear-output-translations)" \
+ --eval '(sb-ext:save-lisp-and-die "travissbcl" :executable t)' \
+
+chmod +x travissbcl
+travisname=travissbcl-$(git rev-parse --short HEAD)
+mv travissbcl $travisname
+
+echo "You should upload via the command: scp $travisname nami:/opt/travis/sbcls/style-checker/"
+echo "You should also set travisname in .travis.yml to $travisname"
+
+rm -rf tmp
--- /dev/null
+(setf *compile-print* nil)
+(require 'asdf)
+(setf asdf:*central-registry* (list #p"deps/"))
+(asdf:load-system :style-checker.internal)
+(asdf:load-system :style-checker-test.internal)
+
+(format t "~%~c[1;33mRunning Tests~c[0m~%" #\Esc #\Esc)
+(when (not (style-checker-test:run-all-tests))
+ (format t "~c[1;31mFailed tests!~c[0m~%" #\Esc #\Esc)
+ (sb-ext:exit :code 1))
+
+(format t "~%~c[1;33mChecking Style~c[0m~%" #\Esc #\Esc)
+(when (not (syntax-checker:pretty-print-check-directory "src"))
+ (format t "~c[1;31mFailed style check!~c[0m~%" #\Esc #\Esc)
+ (sb-ext:exit :code 1))
+
+(format t "~c[1;32mSuccess!~c[0m~%" #\Esc #\Esc)
+(sb-ext:exit :code 0)
--- /dev/null
+../src/test/style-checker-test.asd
\ No newline at end of file
--- /dev/null
+../src/main/style-checker.asd
\ No newline at end of file
+; The systems are split up into two because travis will run more smoothly
+; if we use a custom built sbcl that has all the deps pre-loaded since
+; we are sure those will work just fine :)
+;
+; You should link to this file in your systems directory, or however you
+; handle your asdf configurations. Then just (asdf:load-system :clnl)
+;
+; There's probably a better way, but I don't know it
+
+(asdf:defsystem style-checker.internal
+ :serial t
+ :components ((:file "package") (:file "syntax-checker")))
+
(asdf:defsystem style-checker
:name "Style Checker"
:version "0.1"
:maintainer "Frank Duncan (frank@kank.com)"
:author "Frank Duncan (frank@kank.com)"
:serial t
- :components ((:file "package") (:file "syntax-checker"))
- :depends-on (:cl-ppcre))
+ :depends-on (:cl-ppcre :style-checker.internal))
(let ((seq (make-sequence sequence-type (file-length str)))) (read-sequence seq str) seq)))
(defun check-file (file)
+ "CHECK-FILE FILE => RESULT
+
+ RESULT: SUCCESS-RESULT | FAILURE-RESULT
+ SUCCESS-RESULT: (:success FILENAME)
+ FAILURE-RESULT: (:success FILENAME MSG LINE-NO COL-NO)
+
+ARGUMENTS AND VALUES
+
+ FILE: a pathname
+ FILENAME: the file this check was run on
+ MSG: a string containing the failure message
+ LINE-NO: an integer, the line number on which the failure appeared
+ COL-NO: an integer, the column number on which the failure appeared
+
+DESCRIPTION:
+
+ CHECK-FILE runs all the checks against a file and returns
+ as soon as the first style error is found.
+
+EXAMPLES:
+
+ (check-file #P\"path/to/file.lisp\") => (:success \"path/to/file.lisp\")
+ (check-file #P\"path/to/error.lisp\") => (:failure \"path/to/error.lisp\" \"File cannot end with empty line\" 20 0)"
+
(if (string= "package" (pathname-name file))
(set-state :normal)
(set-state :begin))
--- /dev/null
+(in-package #:style-checker-test)
+
+(defvar *tests* nil)
+
+(defmacro deftest (filename success &optional msg line-no col-no)
+ `(push
+ (lambda ()
+ (let
+ ((green (format nil "~c[1;32m" #\Esc))
+ (red (format nil "~c[1;31m" #\Esc))
+ (result (syntax-checker:check-file ,filename)))
+ (cond
+ ((not (eql ,success (car result)))
+ (format t "~A- ~A failed, expected ~A and got ~A~c[0m~%"
+ red ,filename ,success (car result) #\Esc))
+ ((and (eql :failure ,success) (string/= ,msg (third result)))
+ (format t "~A- ~A failed, expected msg ~A and got msg ~A~c[0m~%"
+ red ,filename ,msg (third result) #\Esc))
+ ((and (eql :failure ,success) (/= ,line-no (fourth result)))
+ (format t "~A- ~A failed, expected line ~A and got line ~A~c[0m~%"
+ red ,filename ,line-no (fourth result) #\Esc))
+ ((and (eql :failure ,success) (/= ,col-no (fifth result)))
+ (format t "~A- ~A failed, expected column ~A and got column ~A~c[0m~%"
+ red ,filename ,col-no (fifth result) #\Esc))
+ (t (format t "~A- ~A passed ~c[0m~%" green ,filename #\Esc) t))))
+ *tests*))
+
+; This really is just here to check against regressions
+(defun run-all-tests ()
+ (let
+ ((results (mapcar #'funcall *tests*)))
+ (every #'identity results)))
+
+(deftest #P"resources/commentneedsspace.lisp" :failure "Multiline top level forms must be separated by a space" 6 0)
+(deftest #P"resources/emptylineatend.lisp" :failure "Must not end with empty line" 8 0)
+(deftest #P"resources/good.lisp" :success)
+(deftest #P"resources/goodcomment.lisp" :success)
+(deftest #P"resources/hangingcloseparens1.lisp" :failure "No hanging close parens" 11 0)
+(deftest #P"resources/hangingcloseparens2.lisp" :failure "No hanging close parens" 12 1)
+(deftest #P"resources/internalsymbols.lisp" :failure "No internal symbols from other packages" 6 22)
+(deftest #P"resources/invalidindent1.lisp" :failure "All form elements must be indented equally" 9 5)
+(deftest #P"resources/invalidindent2.lisp" :failure "All form elements must be indented equally" 11 6)
+(deftest #P"resources/longform.lisp" :failure "Forms can't be over 50 lines long" 117 60)
+(deftest #P"resources/longline.lisp" :failure "Line longer than 120 characters" 2 0)
+(deftest #P"resources/newlineafteropenparens.lisp" :failure "No new line after opening form" 11 5)
+(deftest #P"resources/nopackage.lisp" :failure "Must begin with in-package form" 0 0)
+(deftest #P"resources/package.lisp" :success)
+(deftest #P"resources/spaceafteropenparens.lisp" :failure "No space after opening parens" 11 5)
+(deftest #P"resources/tabs.lisp" :failure "Must not use tabs" 4 0)
+(deftest #P"resources/toplevelindented.lisp" :failure "Top level forms must begin on first column" 3 1)
+(deftest #P"resources/twoemptylines.lisp" :failure "Must not have two empty lines in a row" 2 0)
+(deftest #P"resources/twoemptylineswithcomment.lisp" :failure "Must not have two empty lines in a row" 8 0)
+(deftest #P"resources/twoinpackage.lisp" :failure "Only one in-package per file" 9 0)
+(deftest #P"resources/twospaces.lisp" :failure "Only one space between items of a form" 8 6)
+(deftest #P"resources/unspacedforms.lisp" :failure "Multiline top level forms must be separated by a space" 4 0)
+(deftest #P"resources/whitespaceendline.lisp" :failure "No whitespace at end of line" 4 106)
+(deftest #P"resources/whitespacelines.lisp" :failure "No whitespace only lines" 1 1)
--- /dev/null
+(defpackage #:style-checker-test (:use :common-lisp)
+ (:export :run-all-tests))
--- /dev/null
+; For why this is the way it is, see src/main/style-checker.asd
+(asdf:defsystem style-checker-test.internal
+ :components ((:file "package")
+ (:file "main")))
+
+(asdf:defsystem style-checker-test
+ :name "Experiment Tests"
+ :version "0.0.1"
+ :maintainer "Frank Duncan (frank@kank.com)"
+ :author "Frank Duncan (frank@kank.com)"
+ :serial t
+ :depends-on (:style-checker style-checker-test.internal))