hassle_rs/intellisense/
wrapper.rs1use com::Interface;
2
3use crate::intellisense::ffi::*;
4use crate::os::{CoTaskMemFree, BSTR, LPSTR};
5use crate::utils::Result;
6use crate::wrapper::Dxc;
7use std::ffi::CString;
8use std::mem::ManuallyDrop;
9
10pub struct DxcIntellisense {
11 inner: IDxcIntelliSense,
12}
13
14impl DxcIntellisense {
15 fn new(inner: IDxcIntelliSense) -> Self {
16 Self { inner }
17 }
18
19 pub fn get_default_editing_tu_options(&self) -> Result<DxcTranslationUnitFlags> {
20 let mut options: DxcTranslationUnitFlags = DxcTranslationUnitFlags::NONE;
21 unsafe { self.inner.get_default_editing_tu_options(&mut options) }
22 .result_with_success(options)
23 }
24
25 pub fn create_index(&self) -> Result<DxcIndex> {
26 let mut index = None;
27 unsafe { self.inner.create_index(&mut index) }.result()?;
28 Ok(DxcIndex::new(index.unwrap()))
29 }
30
31 pub fn create_unsaved_file(&self, file_name: &str, contents: &str) -> Result<DxcUnsavedFile> {
32 let c_file_name = CString::new(file_name).expect("Failed to convert `file_name`");
33 let c_contents = CString::new(contents).expect("Failed to convert `contents`");
34
35 let mut file = None;
36 unsafe {
37 self.inner.create_unsaved_file(
38 c_file_name.as_ptr(),
39 c_contents.as_ptr(),
40 contents.len() as u32,
41 &mut file,
42 )
43 }
44 .result()?;
45 Ok(DxcUnsavedFile::new(file.unwrap()))
46 }
47}
48
49pub struct DxcIndex {
50 inner: IDxcIndex,
51}
52
53impl DxcIndex {
54 fn new(inner: IDxcIndex) -> Self {
55 Self { inner }
56 }
57}
58
59impl DxcIndex {
60 pub fn parse_translation_unit(
61 &self,
62 source_filename: &str,
63 args: &[&str],
64 unsaved_files: &[&DxcUnsavedFile],
65 options: DxcTranslationUnitFlags,
66 ) -> Result<DxcTranslationUnit> {
67 let c_source_filename =
68 CString::new(source_filename).expect("Failed to convert `source_filename`");
69
70 let uf = unsaved_files
71 .iter()
72 .map(|unsaved_file| unsaved_file.inner.clone())
73 .collect::<Vec<_>>();
74
75 let mut c_args: Vec<CString> = vec![];
76 let mut cliargs = vec![];
77
78 for arg in args.iter() {
79 let c_arg = CString::new(*arg).expect("Failed to convert `arg`");
80 cliargs.push(c_arg.as_ptr().cast());
81 c_args.push(c_arg);
82 }
83
84 let mut tu = None;
85
86 unsafe {
87 self.inner.parse_translation_unit(
88 c_source_filename.as_ptr().cast(),
89 cliargs.as_ptr(),
90 cliargs.len() as i32,
91 uf.as_ptr(),
92 uf.len() as u32,
93 options,
94 &mut tu,
95 )
96 }
97 .result()?;
98 Ok(DxcTranslationUnit::new(tu.unwrap()))
99 }
100}
101
102pub struct DxcUnsavedFile {
103 inner: IDxcUnsavedFile,
104}
105
106impl DxcUnsavedFile {
107 pub fn get_length(&self) -> Result<u32> {
108 let mut length: u32 = 0;
109 unsafe { self.inner.get_length(&mut length) }.result_with_success(length)
110 }
111
112 fn new(inner: IDxcUnsavedFile) -> Self {
113 DxcUnsavedFile { inner }
114 }
115}
116
117pub struct DxcTranslationUnit {
118 inner: IDxcTranslationUnit,
119}
120
121impl DxcTranslationUnit {
122 fn new(inner: IDxcTranslationUnit) -> Self {
123 DxcTranslationUnit { inner }
124 }
125
126 pub fn get_file(&self, name: &[u8]) -> Result<DxcFile> {
127 let mut file = None;
128 unsafe { self.inner.get_file(name.as_ptr(), &mut file) }.result()?;
129 Ok(DxcFile::new(file.unwrap()))
130 }
131
132 pub fn get_cursor(&self) -> Result<DxcCursor> {
133 let mut cursor = None;
134 unsafe { self.inner.get_cursor(&mut cursor) }.result()?;
135 Ok(DxcCursor::new(cursor.unwrap()))
136 }
137}
138
139pub struct DxcCursor {
140 inner: IDxcCursor,
141}
142
143impl DxcCursor {
144 fn new(inner: IDxcCursor) -> Self {
145 DxcCursor { inner }
146 }
147
148 pub fn get_children(&self, skip: u32, max_count: u32) -> Result<Vec<DxcCursor>> {
149 let mut result: *mut IDxcCursor = std::ptr::null_mut();
150 let mut result_length: u32 = 0;
151
152 unsafe {
153 self.inner
154 .get_children(skip, max_count, &mut result_length, &mut result)
155 }
156 .result()?;
157
158 let child_cursors = ManuallyDrop::new(unsafe {
164 Vec::from_raw_parts(result, result_length as usize, result_length as usize)
165 })
166 .drain(..)
167 .map(DxcCursor::new)
168 .collect::<Vec<_>>();
169
170 unsafe { CoTaskMemFree(result.cast()) };
171 Ok(child_cursors)
172 }
173
174 pub fn get_all_children(&self) -> Result<Vec<DxcCursor>> {
175 const MAX_CHILDREN_PER_CHUNK: u32 = 10;
176 let mut children = vec![];
177
178 loop {
179 let res = self.get_children(children.len() as u32, MAX_CHILDREN_PER_CHUNK)?;
180 let res_len = res.len();
181 children.extend(res);
182 if res_len < MAX_CHILDREN_PER_CHUNK as usize {
183 break Ok(children);
184 }
185 }
186 }
187
188 pub fn get_extent(&self) -> Result<DxcSourceRange> {
189 let mut range = None;
190 unsafe { self.inner.get_extent(&mut range) }.result()?;
191 Ok(DxcSourceRange::new(range.unwrap()))
192 }
193
194 pub fn get_location(&self) -> Result<DxcSourceLocation> {
195 let mut location = None;
196 unsafe { self.inner.get_location(&mut location) }.result()?;
197 Ok(DxcSourceLocation::new(location.unwrap()))
198 }
199
200 pub fn get_display_name(&self) -> Result<String> {
201 let mut name: BSTR = std::ptr::null_mut();
202 unsafe { self.inner.get_display_name(&mut name) }.result()?;
203 Ok(crate::utils::from_bstr(name))
204 }
205
206 pub fn get_formatted_name(&self, formatting: DxcCursorFormatting) -> Result<String> {
207 let mut name: BSTR = std::ptr::null_mut();
208 unsafe { self.inner.get_formatted_name(formatting, &mut name) }.result()?;
209 Ok(crate::utils::from_bstr(name))
210 }
211
212 pub fn get_qualified_name(&self, include_template_args: bool) -> Result<String> {
213 let mut name: BSTR = std::ptr::null_mut();
214 unsafe {
215 self.inner
216 .get_qualified_name(include_template_args, &mut name)
217 }
218 .result()?;
219 Ok(crate::utils::from_bstr(name))
220 }
221
222 pub fn get_kind(&self) -> Result<DxcCursorKind> {
223 let mut cursor_kind: DxcCursorKind = DxcCursorKind::UNEXPOSED_DECL;
224 unsafe { self.inner.get_kind(&mut cursor_kind) }.result_with_success(cursor_kind)
225 }
226
227 pub fn get_kind_flags(&self) -> Result<DxcCursorKindFlags> {
228 let mut cursor_kind_flags: DxcCursorKindFlags = DxcCursorKindFlags::NONE;
229 unsafe { self.inner.get_kind_flags(&mut cursor_kind_flags) }
230 .result_with_success(cursor_kind_flags)
231 }
232
233 pub fn get_semantic_parent(&self) -> Result<DxcCursor> {
234 let mut inner = None;
235 unsafe { self.inner.get_semantic_parent(&mut inner) }.result()?;
236 Ok(DxcCursor::new(inner.unwrap()))
237 }
238
239 pub fn get_lexical_parent(&self) -> Result<DxcCursor> {
240 let mut inner = None;
241 unsafe { self.inner.get_lexical_parent(&mut inner) }.result()?;
242 Ok(DxcCursor::new(inner.unwrap()))
243 }
244
245 pub fn get_cursor_type(&self) -> Result<DxcType> {
246 let mut inner = None;
247 unsafe { self.inner.get_cursor_type(&mut inner) }.result()?;
248 Ok(DxcType::new(inner.unwrap()))
249 }
250
251 pub fn get_num_arguments(&self) -> Result<i32> {
252 let mut result: i32 = 0;
253
254 unsafe { self.inner.get_num_arguments(&mut result) }.result_with_success(result)
255 }
256
257 pub fn get_argument_at(&self, index: i32) -> Result<DxcCursor> {
258 let mut inner = None;
259 unsafe { self.inner.get_argument_at(index, &mut inner) }.result()?;
260 Ok(DxcCursor::new(inner.unwrap()))
261 }
262
263 pub fn get_referenced_cursor(&self) -> Result<DxcCursor> {
264 let mut inner = None;
265 unsafe { self.inner.get_referenced_cursor(&mut inner) }.result()?;
266 Ok(DxcCursor::new(inner.unwrap()))
267 }
268
269 pub fn get_definition_cursor(&self) -> Result<DxcCursor> {
270 let mut inner = None;
271 unsafe { self.inner.get_definition_cursor(&mut inner) }.result()?;
272 Ok(DxcCursor::new(inner.unwrap()))
273 }
274
275 pub fn find_references_in_file(
276 &self,
277 file: &DxcFile,
278 skip: u32,
279 top: u32,
280 ) -> Result<Vec<DxcCursor>> {
281 let mut result: *mut IDxcCursor = std::ptr::null_mut();
282 let mut result_length: u32 = 0;
283
284 unsafe {
285 self.inner.find_references_in_file(
286 &file.inner,
287 skip,
288 top,
289 &mut result_length,
290 &mut result,
291 )
292 }
293 .result()?;
294
295 let child_cursors = ManuallyDrop::new(unsafe {
301 Vec::from_raw_parts(result, result_length as usize, result_length as usize)
302 })
303 .drain(..)
304 .map(DxcCursor::new)
305 .collect::<Vec<_>>();
306
307 unsafe { CoTaskMemFree(result.cast()) };
308 Ok(child_cursors)
309 }
310
311 pub fn get_spelling(&self) -> Result<String> {
312 let mut spelling: LPSTR = std::ptr::null_mut();
313 unsafe { self.inner.get_spelling(&mut spelling) }.result()?;
314 Ok(crate::utils::from_lpstr(spelling))
315 }
316
317 pub fn is_equal_to(&self, other: &DxcCursor) -> Result<bool> {
318 let mut result: bool = false;
319 unsafe { self.inner.is_equal_to(&other.inner, &mut result) }.result_with_success(result)
320 }
321
322 pub fn is_null(&mut self) -> Result<bool> {
323 let mut result: bool = false;
324 unsafe { IDxcCursor::is_null(&self.inner, &mut result) }.result_with_success(result)
325 }
326
327 pub fn is_definition(&self) -> Result<bool> {
328 let mut result: bool = false;
329 unsafe { self.inner.is_definition(&mut result) }.result_with_success(result)
330 }
331
332 pub fn get_snapped_child(&self, location: &DxcSourceLocation) -> Result<DxcCursor> {
333 let mut inner = None;
334 unsafe { self.inner.get_snapped_child(&location.inner, &mut inner) }.result()?;
335 Ok(DxcCursor::new(inner.unwrap()))
336 }
337
338 pub fn get_source<'a>(&self, source: &'a str) -> Result<&'a str> {
339 let range = self.get_extent()?;
340
341 let DxcSourceOffsets {
342 start_offset,
343 end_offset,
344 } = range.get_offsets()?;
345
346 let source_range = (start_offset as usize)..(end_offset as usize);
347
348 Ok(&source[source_range])
349 }
350}
351
352pub struct DxcType {
353 inner: IDxcType,
354}
355
356impl DxcType {
357 fn new(inner: IDxcType) -> Self {
358 DxcType { inner }
359 }
360
361 pub fn get_spelling(&self) -> Result<String> {
362 let mut spelling: LPSTR = std::ptr::null_mut();
363 unsafe { self.inner.get_spelling(&mut spelling) }
364 .result_with_success(crate::utils::from_lpstr(spelling))
365 }
366}
367
368pub struct DxcSourceLocation {
369 inner: IDxcSourceLocation,
370}
371
372impl std::fmt::Debug for DxcSourceLocation {
373 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
374 f.debug_struct("DxcSourceLocation")
375 .field("inner", &self.inner)
376 .finish()
377 }
378}
379
380impl DxcSourceLocation {
381 fn new(inner: IDxcSourceLocation) -> Self {
382 DxcSourceLocation { inner }
383 }
384}
385
386#[derive(Debug)]
387pub struct DxcSourceOffsets {
388 pub start_offset: u32,
389 pub end_offset: u32,
390}
391
392pub struct DxcSourceRange {
393 inner: IDxcSourceRange,
394}
395
396impl std::fmt::Debug for DxcSourceRange {
397 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
398 f.debug_struct("DxcSourceRange")
399 .field("inner", &self.inner)
400 .finish()
401 }
402}
403
404impl DxcSourceRange {
405 pub fn get_offsets(&self) -> Result<DxcSourceOffsets> {
406 let mut start_offset: u32 = 0;
407 let mut end_offset: u32 = 0;
408 unsafe { self.inner.get_offsets(&mut start_offset, &mut end_offset) }.result_with_success(
409 DxcSourceOffsets {
410 start_offset,
411 end_offset,
412 },
413 )
414 }
415}
416
417impl DxcSourceRange {
418 fn new(inner: IDxcSourceRange) -> Self {
419 DxcSourceRange { inner }
420 }
421}
422
423pub struct DxcFile {
424 inner: IDxcFile,
425}
426
427impl DxcFile {
428 fn new(inner: IDxcFile) -> Self {
429 DxcFile { inner }
430 }
431}
432
433impl Dxc {
434 pub fn create_intellisense(&self) -> Result<DxcIntellisense> {
435 let mut intellisense = None;
436
437 self.get_dxc_create_instance()?(
438 &CLSID_DxcIntelliSense,
439 &IDxcIntelliSense::IID,
440 &mut intellisense,
441 )
442 .result()?;
443 Ok(DxcIntellisense::new(intellisense.unwrap()))
444 }
445}