package pfff

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file stdlib_js.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
(* Yoann Padioleau
 *
 * Copyright (C) 2019 Yoann Padioleau
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation, with the
 * special exception on linking described in file license.txt.
 * 
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the file
 * license.txt for more details.
 *)
open Common
module TH = Token_helpers_js
module E = Entity_code
module F = Ast_fuzzy

(*****************************************************************************)
(* Prelude *)
(*****************************************************************************)
(* This module gives access to the Javascript standard library entities,
 * which is especially useful for Graph_code_js.
 *
 * related: 
 *  - Flow standard lib definitions (small set)
 *    https://github.com/facebook/flow/tree/master/lib
 *  - Typescript standard lib definitions (bigger set)
 *    https://github.com/microsoft/TypeScript/tree/master/src/lib
 *  - TypeScript generator, which generates the .generated.d.ts above
 *    https://github.com/Microsoft/TSJS-lib-generator
 *  - Closure compiler lib definitions (untyped)
 *    https://github.com/google/closure-compiler/tree/master/externs
 *    extended in Semmle
 *    https://github.com/Semmle/ql/tree/master/javascript/externs
 *
 *  - TypeScript definition manager (deprecated)
 *    https://github.com/typings/typings
 *  - High quality Typescript type definitions (looks like the new standard)
 *    http://definitelytyped.org/ especially
 *    https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/globals.d.ts
 *
 * src: https://stackoverflow.com/questions/46696266/where-can-i-find-documentation-for-typescripts-built-in-types-and-standard-libr
 *)

(*****************************************************************************)
(* Types *)
(*****************************************************************************)

(*****************************************************************************)
(* Constants *)
(*****************************************************************************)
let path_stdlib = 
  Filename.concat Config_pfff.path "data/js_stdlib/stdlib.js"

(*****************************************************************************)
(* Helpers *)
(*****************************************************************************)
let extract_defs file = 
  let toks = 
    (* Flow/Typescript and JSX have lexing conflicts *)
    Common.save_excursion Flag_parsing_js.jsx false (fun () ->
     Parse_js.tokens file 
    )
  in
  let toks = Common.exclude TH.is_comment toks in
  let trees = Parse_fuzzy.mk_trees { Parse_fuzzy.
     tokf = TH.info_of_tok;
     kind = TH.token_kind_of_tok;
  } toks 
  in
  (* process only toplevel elements, not the one
   * under 'declare module xx { ... }', by not recursing inside
   * F.Braces
   *)
  let rec aux acc = function
    | [] -> List.rev acc
    | F.Tok("function", _)::F.Tok (s, _)::xs ->
       aux ((E.Function, s)::acc) xs
    | F.Tok("var",_)::F.Tok(s, _)::xs ->
       aux ((E.Global, s)::acc) xs
    | F.Tok("class",_)::F.Tok(s, _)::xs ->
       aux ((E.Class, s)::acc) xs
    | _x::xs -> aux acc xs
  in
  aux [] trees

let add_and_report_if_already_there already file str =
  if Hashtbl.mem already str
  then begin
    let dupfile = Hashtbl.find already str in
    pr2 (spf "entity %s defined both in %s and %s" str dupfile file);
    true
  end else begin
    Hashtbl.replace already str file;
    false
  end

(*****************************************************************************)
(* Stdlib.js generator *)
(*****************************************************************************)

(* example of use:
 * ./codegraph_build -lang js -build_stdlib ~/r2c/other-progs/facebook/flow/lib/core.js  ~/pfff/data/js_stdlib/
 *)
let extract_from_sources files dst =
  let defs = 
    files |> List.map (fun file -> file, extract_defs file) in
  let dstfile = Filename.concat dst "stdlib.js" in
  let auxfile = Filename.concat dst "aux.js" in
  let already = Hashtbl.create 101 in
  let lines = 
    defs |> List.map (fun (file, xs) ->
     ["";
      "// ------------------------------------------------------";
      spf "// from %s" file;
      "// ------------------------------------------------------";
     ] @
     (xs |> Common.map_filter (fun (kind, s) ->
      let str = 
        match kind with
        | E.Function -> spf "function %s() { }" s
        | E.Class -> spf "class %s { }" s
        | E.Global -> spf "var %s;" s
        | _ -> failwith (spf "extract_from_source: unrecognized kind %s" 
                           (E.string_of_entity_kind kind))
      in
     (* Flow allow some overloading so the same function can be defined twice
      * but with different types. Codegraph does not like that.
      * Flow also have the same function name or class in different files.
      *)
      if add_and_report_if_already_there already file str
      then None
      else Some str
     )
    )
   ) |> List.flatten
 in
  let lines = 
     ["//Auto-generated by extract_from_sources (do not edit this file)";] @
     lines @  
     ["";
      "// ------------------------------------------------------";
      "// Aux file";
      "// ------------------------------------------------------";
     ] @
     Common.cat auxfile 
  in
  let s = String.concat "\n" lines in
  Common.write_file ~file:dstfile s;
  pr2 (spf "Standard Javascript library file %s is ready" dstfile);
  ()
OCaml

Innovation. Community. Security.