<commit_before>; *******************************************************************************
; * Copyright (c) 2009 <NAME>.
; * All rights reserved. This program and the accompanying materials
; * are made available under the terms of the Eclipse Public License v1.0
; * which accompanies this distribution, and is available at
; * http://www.eclipse.org/legal/epl-v10.html
; *
; * Contributors: 
; *    <NAME> - initial API and implementation
; *******************************************************************************/
; Totally footprint free embedded evaluation server
; (do not have any namespace / symbol presence)
(ns ccw.debug.serverrepl)

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; library code

(defn on-thread [f] (.start (new Thread f)))

(defn create-server
  "creates and returns a server socket on port, will pass the client
   socket to accept-socket on connection"
  [accept-socket port file-name]
  (on-thread
    #(loop []
       ; (println "port=" port " ; file-name=" file-name)
       (let [ss (java.net.ServerSocket. (if (= port -1) 0 port))]
         (when (= port -1)
           (with-open [fw (java.io.FileWriter. file-name)]
             (.write fw (str (.getLocalPort ss)))))
         (loop []
           (when-not (.isClosed ss)
             (try
               (let [s (.accept ss)]
                 (on-thread (fn []
                              (with-open [s s]
                                (try
                                  (accept-socket s)
                                  (catch Exception e (println "create-server:accept-socket: unexpected exception " (.getMessage e)) (throw e)))))))
               (catch java.net.SocketException e (println "socket exception " (.getMessage e)))
               (catch Exception e (println "create-server: unexpected exception " (.getMessage e))))
             (recur)))
         (recur))))
  nil)

(defn- push-answer [type answer-sexpr dos]
  (let [answer (pr-str answer-sexpr)
        answer-bytes (.getBytes answer "UTF-8")]
    (.writeInt dos type) ; 0 = OK, -1 = KO (exception)
    (.writeInt dos (alength answer-bytes))
    (.write dos answer-bytes 0 (alength answer-bytes))
    (.flush dos)))

; currently just [file-name line-number message]
(defn- serialize-exception
  ([e] (serialize-exception e []))
  ([e v]
    (if-not e
      v
      (let [stack-traces (.getStackTrace e)
            first-stack (aget stack-traces 0)
            file-name (.getFileName first-stack)
            line-number (.getLineNumber first-stack)
            message (.getMessage e)]
        (recur (.getCause e)
          (conj v {"file-name" file-name
                   "line-number" line-number
                   "message" message}))))))

(defn socket-repl
  "starts a repl thread on the iostreams of supplied socket"
  [s]
  (with-open [dis (new java.io.DataInputStream
                    (new java.io.BufferedInputStream (.getInputStream s)))]
    (with-open [dos (new java.io.DataOutputStream (.getOutputStream s))]
      (let [question-bytes-length (.readInt dis)
            question-bytes (make-array Byte/TYPE question-bytes-length)]
        (.readFully dis question-bytes 0 question-bytes-length)
        (try
          (load-string (new String question-bytes "UTF-8"))
          (push-answer 0 (load-string (new String question-bytes "UTF-8")) dos)
          (catch Exception e (push-answer -1 (serialize-exception e) dos)))))))

(create-server socket-repl
  (Integer/valueOf (System/getProperty "clojure.remote.server.port" "-1"))
  (System/getProperty "ccw.debug.serverrepl.file.port"))

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; support code  

(defn- meta-info [v]
  (reduce (fn [m e] (merge m {(first e) (str (second e))})) {} (meta v)))

(defn- symbol-info [s]
  (merge {:type "symbol" :name (str s)} (meta-info (find-var s))))

(defn- var-info [v]
  (merge {:type "var" :name (str v)} (meta-info v)))

(defn- ns-info
  ([n] (ns-info n true))
  ([n insert-symbols?]
    (conj
      {:name ((comp str ns-name) n)
       :type "ns"
       :doc (:doc (meta n))}
      (when insert-symbols?
        [:children
         (apply vector (sort-by :name (map #(var-info (second %)) (ns-interns n))))]))))

(def ns-info-cache (atom nil))

(defn namespaces-info []
  (let [info
        {:name "namespaces" :type "namespaces"
         :children (apply vector (sort-by :name (map ns-info (all-ns))))}]
    (reset! ns-info-cache info) info))

; The following function (splitted-match) taken from vimClojure with the permission of the author.
; Please look for vimClojure license for more detail
(defn splitted-match
  "Splits pattern and candidate at the given delimiters and matches
  the parts of the pattern with the parts of the candidate. Match
  means �startsWith� here."
  [pattern candidate delimiters]
  (if-let [delimiters (seq delimiters)]
    (let [delim (first delimiters)
          pattern-split (.split pattern delim)
          candidate-split (.split candidate delim)]
      (and (<= (count pattern-split) (count candidate-split))
        (reduce (fn [a b] (and a b)) (map (fn [a b] (splitted-match a b (rest delimiters)))
                                       pattern-split
                                       candidate-split))))
    (.startsWith candidate pattern)))

(defn- matching-ns
  "seq of namespaces which match the prefix
  clojure.co matches clojure.core, ...<commit_msg>cleanup<commit_after>; *******************************************************************************
; * Copyright (c) 2009 <NAME>.
; * All rights reserved. This program and the accompanying materials
; * are made available under the terms of the Eclipse Public License v1.0
; * which accompanies this distribution, and is available at
; * http://www.eclipse.org/legal/epl-v10.html
; *
; * Contributors: 
; *    <NAME> - initial API and implementation
; *******************************************************************************/
; Totally footprint free embedded evaluation server
; (do not have any namespace / symbol presence)
(ns ccw.debug.serverrepl)

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; library code

(defn on-thread [f] (.start (new Thread f)))

(defn create-server
  "creates and returns a server socket on port, will pass the client
   socket to accept-socket on connection"
  [accept-socket port file-name]
  (on-thread
    #(loop []
       ; (println "port=" port " ; file-name=" file-name)
       (let [ss (java.net.ServerSocket. (if (= port -1) 0 port))]
         (when (= port -1)
           (with-open [fw (java.io.FileWriter. file-name)]
             (.write fw (str (.getLocalPort ss)))))
         (loop []
           (when-not (.isClosed ss)
             (try
               (let [s (.accept ss)]
                 (on-thread (fn []
                              (with-open [s s]
                                (try
                                  (accept-socket s)
                                  (catch Exception e (println "create-server:accept-socket: unexpected exception " (.getMessage e)) (throw e)))))))
               (catch java.net.SocketException e (println "socket exception " (.getMessage e)))
               (catch Exception e (println "create-server: unexpected exception " (.getMessage e))))
             (recur)))
         (recur))))
  nil)

(defn- push-answer [type answer-sexpr dos]
  (let [answer (pr-str answer-sexpr)
        answer-bytes (.getBytes answer "UTF-8")]
    (.writeInt dos type) ; 0 = OK, -1 = KO (exception)
    (.writeInt dos (alength answer-bytes))
    (.write dos answer-bytes 0 (alength answer-bytes))
    (.flush dos)))

; currently just [file-name line-number message]
(defn- serialize-exception
  ([e] (serialize-exception e []))
  ([e v]
    (if-not e
      v
      (let [stack-traces (.getStackTrace e)
            first-stack (aget stack-traces 0)
            file-name (.getFileName first-stack)
            line-number (.getLineNumber first-stack)
            message (.getMessage e)]
        (recur (.getCause e)
          (conj v {"file-name" file-name
                   "line-number" line-number
                   "message" message}))))))

(defn socket-repl
  "starts a repl thread on the iostreams of supplied socket"
  [s]
  (with-open [dis (new java.io.DataInputStream
                    (new java.io.BufferedInputStream (.getInputStream s)))]
    (with-open [dos (new java.io.DataOutputStream (.getOutputStream s))]
      (let [question-bytes-length (.readInt dis)
            question-bytes (make-array Byte/TYPE question-bytes-length)]
        (.readFully dis question-bytes 0 question-bytes-length)
        (try
          (load-string (new String question-bytes "UTF-8"))
          (push-answer 0 (load-string (new String question-bytes "UTF-8")) dos)
          (catch Exception e (push-answer -1 (serialize-exception e) dos)))))))

(create-server socket-repl
  (Integer/valueOf (System/getProperty "clojure.remote.server.port" "-1"))
  (System/getProperty "ccw.debug.serverrepl.file.port"))

; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; support code  

(defn- meta-info [v]
  (reduce (fn [m e] (merge m {(first e) (str (second e))})) {} (meta v)))

(defn- symbol-info [s]
  (merge {:type "symbol" :name (str s)} (meta-info (find-var s))))

(defn- var-info [v]
  (merge {:type "var" :name (str v)} (meta-info v)))

(defn- ns-info
  ([n] (ns-info n true))
  ([n insert-symbols?]
    (conj
      {:name ((comp str ns-name) n)
       :type "ns"
       :doc (:doc (meta n))}
      (when insert-symbols?
        [:children
         (apply vector (sort-by :name (map #(var-info (second %)) (ns-interns n))))]))))

(defn namespaces-info []
  {:name "namespaces" :type "namespaces"
   :children (apply vector (sort-by :name (map ns-info (all-ns))))})

; The following function (splitted-match) taken from vimClojure with the permission of the author.
; Please look for vimClojure license for more detail
(defn splitted-match
  "Splits pattern and candidate at the given delimiters and matches
  the parts of the pattern with the parts of the candidate. Match
  means �startsWith� here."
  [pattern candidate delimiters]
  (if-let [delimiters (seq delimiters)]
    (let [delim (first delimiters)
          pattern-split (.split pattern delim)
          candidate-split (.split candidate delim)]
      (and (<= (count pattern-split) (count candidate-split))
        (reduce (fn [a b] (and a b)) (map (fn [a b] (splitted-match a b (rest delimiters)))
                                       pattern-split
                                       candidate-split))))
    (.startsWith candidate pattern)))

(defn- matching-ns
  "seq of namespaces which match the prefix
  clojure.co matches clojure.core, ...
{'fraction_non_alphanumeric': 0.18516808274843, 'fraction_numerical': 0.004063538973032878, 'mean_word_length': 2.5574901445466494, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7375043', 'n_tokens_mistral': 3366, 'n_tokens_neox': 3165, 'n_words': 1010}