Add position metadata to desugaring
[hiphop-php.git] / hphp / hack / test / integration / test_write_symbol_info.py
blobd4c0da08771c1db857e883e65424d009ab852338
1 # pyre-strict
2 from __future__ import absolute_import, division, print_function, unicode_literals
4 import json
5 import os
6 from typing import ClassVar, Dict, List, Optional, Type
8 import test_case
9 from common_tests import CommonTestDriver
10 from glean.schema.hack.types import (
11 ClassConstDeclaration,
12 ClassConstDefinition,
13 ClassDeclaration,
14 ClassDefinition,
15 DeclarationComment,
16 DeclarationLocation,
17 DeclarationSpan,
18 EnumDeclaration,
19 EnumDefinition,
20 Enumerator,
21 FileDeclarations,
22 FileXRefs,
23 FunctionDeclaration,
24 FunctionDefinition,
25 GlobalConstDeclaration,
26 GlobalConstDefinition,
27 InterfaceDeclaration,
28 InterfaceDefinition,
29 MethodDeclaration,
30 MethodDefinition,
31 NamespaceQName,
32 PropertyDeclaration,
33 PropertyDefinition,
34 QName,
35 TraitDeclaration,
36 TraitDefinition,
37 TypeConstDeclaration,
38 TypeConstDefinition,
39 TypedefDeclaration,
41 from glean.schema.src.types import FileLines
42 from hh_paths import hh_server
43 from thrift.py3 import Protocol, Struct, deserialize
46 class WriteSymbolInfoTests(test_case.TestCase[CommonTestDriver]):
47 write_repo: ClassVar[str] = "default_symbol_info_test_dir"
48 valid_keys: ClassVar[Dict[str, List[object]]] = {}
50 @classmethod
51 def get_test_driver(cls) -> CommonTestDriver:
52 return CommonTestDriver()
54 def setUp(self) -> None:
55 super().setUp()
56 with open(os.path.join(self.test_driver.repo_dir, "hh.conf"), "w") as f:
57 f.write(
58 r"""
59 # some comment
60 use_mini_state = true
61 use_watchman = true
62 watchman_subscribe_v2 = true
63 lazy_decl = true
64 lazy_parse = true
65 lazy_init2 = true
66 incremental_init = true
67 enable_fuzzy_search = false
68 max_workers = 2
69 """
72 def tearDown(self) -> None:
73 try:
74 # driver.tearDown() can throw if the env is not as expected
75 super().tearDown()
76 except Exception as e:
77 print("Error during test teardown : {}".format(str(e)))
79 @classmethod
80 def setUpClass(cls) -> None:
81 super().setUpClass()
82 test_driver = cls._test_driver
83 if test_driver is not None:
84 cls.write_repo = os.path.join(test_driver.repo_dir, "symbol_info_test_dir")
86 def verify_json(self) -> None:
87 for filename in os.listdir(self.write_repo):
88 self.assertTrue(
89 filename.endswith(".json"), "All output files are in JSON format"
92 with open(os.path.join(self.write_repo, filename)) as file:
93 json_predicate_list = json.load(file)
94 for pred_obj in json_predicate_list:
95 self.assertTrue(
96 "predicate" in pred_obj and "facts" in pred_obj,
97 "JSON predicate has correct form",
100 fact_type = self.predicate_name_to_type(pred_obj["predicate"])
101 if fact_type is None:
102 self.fail(
103 "Could not find matching Thrift definition for {}".format(
104 pred_obj["predicate"]
108 for fact in pred_obj["facts"]:
109 try:
110 deserialize(
111 fact_type,
112 json.dumps(fact).encode("UTF-8"),
113 protocol=Protocol.JSON,
115 except Exception as e:
116 self.fail(
117 "Could not deserialize {} fact JSON: {}\nDeserialization error: {}".format(
118 fact_type, fact, e
122 def predicate_name_to_type(self, predicate_name: str) -> Optional[Type[Struct]]:
123 ver = 3
124 predicate_dict = {
125 "hack.ClassConstDeclaration.{}".format(ver): ClassConstDeclaration,
126 "hack.ClassConstDefinition.{}".format(ver): ClassConstDefinition,
127 "hack.ClassDeclaration.{}".format(ver): ClassDeclaration,
128 "hack.ClassDefinition.{}".format(ver): ClassDefinition,
129 "hack.DeclarationComment.{}".format(ver): DeclarationComment,
130 "hack.DeclarationLocation.{}".format(ver): DeclarationLocation,
131 "hack.DeclarationSpan.{}".format(ver): DeclarationSpan,
132 "hack.EnumDeclaration.{}".format(ver): EnumDeclaration,
133 "hack.EnumDefinition.{}".format(ver): EnumDefinition,
134 "hack.Enumerator.{}".format(ver): Enumerator,
135 "hack.FileDeclarations.{}".format(ver): FileDeclarations,
136 "hack.FileXRefs.{}".format(ver): FileXRefs,
137 "hack.FunctionDeclaration.{}".format(ver): FunctionDeclaration,
138 "hack.FunctionDefinition.{}".format(ver): FunctionDefinition,
139 "hack.GlobalConstDeclaration.{}".format(ver): GlobalConstDeclaration,
140 "hack.GlobalConstDefinition.{}".format(ver): GlobalConstDefinition,
141 "hack.InterfaceDeclaration.{}".format(ver): InterfaceDeclaration,
142 "hack.InterfaceDefinition.{}".format(ver): InterfaceDefinition,
143 "hack.MethodDeclaration.{}".format(ver): MethodDeclaration,
144 "hack.MethodDefinition.{}".format(ver): MethodDefinition,
145 "hack.NamespaceQName.{}".format(ver): NamespaceQName,
146 "hack.PropertyDeclaration.{}".format(ver): PropertyDeclaration,
147 "hack.PropertyDefinition.{}".format(ver): PropertyDefinition,
148 "hack.QName.{}".format(ver): QName,
149 "hack.TraitDeclaration.{}".format(ver): TraitDeclaration,
150 "hack.TraitDefinition.{}".format(ver): TraitDefinition,
151 "hack.TypeConstDeclaration.{}".format(ver): TypeConstDeclaration,
152 "hack.TypeConstDefinition.{}".format(ver): TypeConstDefinition,
153 "hack.TypedefDeclaration.{}".format(ver): TypedefDeclaration,
154 "src.FileLines.1": FileLines,
156 return predicate_dict.get(predicate_name)
158 def start_hh_server(
159 self,
160 changed_files: Optional[List[str]] = None,
161 saved_state_path: Optional[str] = None,
162 args: Optional[List[str]] = None,
163 ) -> None:
164 """Start an hh_server. changed_files is ignored here (as it
165 has no meaning) and is only exposed in this API for the derived
166 classes.
168 if changed_files is None:
169 changed_files = []
170 if args is None:
171 args = []
172 cmd = [
173 hh_server,
174 "--max-procs",
175 "2",
176 "--config",
177 "symbolindex_search_provider=NoIndex",
178 self.test_driver.repo_dir,
179 ] + args
180 self.test_driver.proc_call(cmd)
182 def test_json_format(self) -> None:
183 print("repo_contents : {}".format(os.listdir(self.test_driver.repo_dir)))
184 args: Optional[List[str]] = None
185 args = ["--write-symbol-info", self.write_repo]
186 self.start_hh_server(args=args)
187 self.verify_json()