2014-01-13 120 views
0

我有用clojure編寫的多個(3k +)腳本(每個腳本不依賴於任何其他腳本)。 這些腳本是用Clojure 1.2編寫的,我想用舊的contrib庫來分析它們。到目前爲止,我只是簡單地搜索clojure.contrib\.[0-9a-z\.\-]*的文件,但我還想從腳本中使用的這些contrib庫中找到特定的函數。分析clojure程序的依賴關係

有沒有比正則表達式更好的方法嗎?

任何可以讓我解析字符串(包含Clojure程序)並輕鬆提取依賴關係的clojure庫?

+0

如果使用雷音,他們試圖雷音DEPS:樹一些靈感 – Chiron

+0

[slamhound(https://github.com/technomancy/slamhound)執行類似各種分析。可能值得研究。 –

回答

1

使用core.analyze您可能會接近。

這是一個老例子,它會給你所有的頂級功能/每個項目文件的元素。

您應該能夠輕鬆修改parse-clojure-file函數來分析函數樹來檢查調用。使用leiningen.core.projectanalyze.core

設置依賴關係:從磁盤和工藝

(defn parse-clojure-file 
    "Reads a clojure source file from disk 
    and returns a sequence of hashes of 
    first level objects 
    {:type defn :name parse-clojure-file} 
    {:type ns :name clandombg.project} 
    ..." 
    [file] 
    (let [forms (analyze.core/forms-seq 
       (java.io.PushbackReader. (clojure.java.io/reader file)))] 
    (reduce (fn [file-obj form] 
       (conj file-obj {:type (first form) :name (second form)})) 
     [] forms))) 

樹中的所有項目文件的

(ns dependencies.project 
    (:require 
    [leiningen.core.project :as project] 
    [analyze.core :as analyze] 
    [clojure.java.io]) 
    (:import 
    (java.io PushbackReader))) 

讀取文件,返回的哈希地圖由相對路徑索引:

(defn traverse-source-tree 
    "Traverses a source directory recursively and returns 
    a collection of files keyed by relative-path and content 
    the file first level objects" 
    [directory] 
    (let [files (file-seq (clojure.java.io/file directory)) 
     clj-files (filter #(re-matches #".+\.clj$|.+\.cljs$" (.getName %)) files)] 
    (reduce (fn [project file] 
       (let [relative-path (clojure.string/replace (.getPath file) directory "")] 
       (assoc project 
        relative-path 
        (merge 
        (parse-clojure-file file) 
        {:relative-path relative-path})))) 
      {} clj-files))) 

入門點:

(defn parse-project 
    "Reads a project file from disk and parses its source 
    files, returns a clojure encoded string" 
    [project-path] 
    (let [project (project/read project-path)] 
    (reduce #(assoc %1 %2 (traverse-source-tree %2)) 
          {} 
          (:source-paths project)))) 

調用與:

(parse-project "path/to/project.clj") 
+0

謝謝。看起來不錯,但畢竟我用正則表達式做了它(我的腳本有很多「:使用」導入,所以我將不得不評估它們以正確解析所有函數的命名空間)。 –