PageRenderTime 61ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 2ms

/SHFB/Source/MRefBuilder/CCI/Nodes.cs

#
C# | 12670 lines | 11248 code | 573 blank | 849 comment | 3031 complexity | 0ba47bd13f8400a94c762348c4ab196d MD5 | raw file
Possible License(s): CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. // Copyright Š Microsoft Corporation.
  2. // This source file is subject to the Microsoft Permissive License.
  3. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
  4. // All other rights reserved.
  5. // Change history:
  6. // 02/03/2012 - EFW - Fixed Method.ImplicitlyImplementedInterfaceMethods so that it recognizes interface
  7. // member matches when the return type is generic.
  8. // 03/28/2012 - EFW - Fixed TypeNode.Attributes so that it won't get stuck in an endless loop if a type's
  9. // attribute references the type being parsed.
  10. // 04/04/2012 - EFW - Fixed TypeNode.NestedTypes so that it won't get stuck in an endless loop when a type
  11. // contains a nested type that itself implements a nested type from within the containing type.
  12. // 11/30/2012 - EFW - Added updates based on changes submitted by ComponentOne to fix crashes caused by
  13. // obfuscated member names.
  14. // 11/21/2013 - EFW - Cleared out the conditional statements and unused code and updated based on changes to
  15. // ListTemplate.cs.
  16. // 03/14/2014 - EFW - Fixed bug in TypeNode.GetMatchingMethod() reported by SHarwell.
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Globalization;
  20. using System.Compiler.Metadata;
  21. using System.Diagnostics;
  22. using System.IO;
  23. using System.Text;
  24. using System.Xml;
  25. using BindingFlags = System.Reflection.BindingFlags;
  26. namespace System.Compiler
  27. {
  28. /// <summary>
  29. /// This interface can be used to link an arbitrary source text provider into an IR tree via a DocumentText instance.
  30. /// </summary>
  31. public interface ISourceText
  32. {
  33. /// <summary>
  34. /// The number of characters in the source text.
  35. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  36. /// </summary>
  37. int Length { get; }
  38. /// <summary>
  39. /// Retrieves a substring from this instance. The substring starts with the character at the specified index and has a specified length.
  40. /// </summary>
  41. string Substring(int startIndex, int length);
  42. /// <summary>
  43. /// Retrieves the character at the given position. The first character is at position zero.
  44. /// </summary>
  45. char this[int position] { get; }
  46. /// <summary>
  47. /// Indicates that the text has been fully scanned and further references to the text are expected to be infrequent.
  48. /// The underlying object can now choose to clear cached information if it comes under resource pressure.
  49. /// </summary>
  50. void MakeCollectible();
  51. }
  52. public unsafe interface ISourceTextBuffer : ISourceText
  53. {
  54. /// <summary>
  55. /// Returns null unless the implementer is based on an ASCII buffer that stays alive as long at the implementer itself.
  56. /// An implementer that returns a non-null value is merely a wrapper to keep the buffer alive. No further methods will
  57. /// be called on the interface in this case.
  58. /// </summary>
  59. byte* Buffer { get; }
  60. }
  61. /// <summary>
  62. /// This class provides a uniform interface to program sources provided in the form of Unicode strings,
  63. /// unsafe pointers to ASCII buffers (as obtained from a memory mapped file, for instance) as well as
  64. /// arbitrary source text providers that implement the ISourceText interface.
  65. /// </summary>
  66. public sealed unsafe class DocumentText
  67. {
  68. /// <summary>
  69. /// If this is not null it is used to obtain 8-bit ASCII characters.
  70. /// </summary>
  71. public byte* AsciiStringPtr;
  72. /// <summary>
  73. /// If this is not null it represents a Unicode string encoded as UTF16.
  74. /// </summary>
  75. public string Source;
  76. /// <summary>
  77. /// If this is not null the object implement ISourceText provides some way to get at individual characters and substrings.
  78. /// </summary>
  79. public ISourceText TextProvider;
  80. /// <summary>
  81. /// The number of characters in the source document.
  82. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  83. /// </summary>
  84. public int Length;
  85. public DocumentText(string source)
  86. {
  87. if(source == null) { Debug.Assert(false); return; }
  88. this.Source = source;
  89. this.Length = source.Length;
  90. }
  91. public DocumentText(ISourceText textProvider)
  92. {
  93. if(textProvider == null) { Debug.Assert(false); return; }
  94. this.TextProvider = textProvider;
  95. this.Length = textProvider.Length;
  96. }
  97. public unsafe DocumentText(ISourceTextBuffer textProvider)
  98. {
  99. if(textProvider == null) { Debug.Assert(false); return; }
  100. this.TextProvider = textProvider;
  101. this.AsciiStringPtr = textProvider.Buffer;
  102. this.Length = textProvider.Length;
  103. }
  104. /// <summary>
  105. /// Compare this.Substring(offset, length) for equality with str.
  106. /// Call this only if str.Length is known to be equal to length.
  107. /// </summary>
  108. public bool Equals(string str, int position, int length)
  109. { //TODO: (int position, int length, string str)
  110. if(str == null) { Debug.Assert(false); return false; }
  111. if(str.Length != length) { Debug.Assert(false); return false; }
  112. if(position < 0 || position + length > this.Length) { Debug.Assert(false); return false; }
  113. unsafe
  114. {
  115. byte* p = this.AsciiStringPtr;
  116. if(p != null)
  117. {
  118. for(int i = position, j = 0; j < length; i++, j++)
  119. if(((char)*(p + i)) != str[j])
  120. return false;
  121. return true;
  122. }
  123. }
  124. string source = this.Source;
  125. if(source != null)
  126. {
  127. for(int i = position, j = 0; j < length; i++, j++)
  128. if(source[i] != str[j])
  129. return false;
  130. return true;
  131. }
  132. ISourceText myProvider = this.TextProvider;
  133. if(myProvider == null) { Debug.Assert(false); return false; }
  134. for(int i = position, j = 0; j < length; i++, j++)
  135. if(myProvider[i] != str[j])
  136. return false;
  137. return true;
  138. }
  139. /// <summary>
  140. /// Compares the substring of the specified length starting at offset, with the substring in DocumentText starting at textOffset.
  141. /// </summary>
  142. /// <param name="offset">The index of the first character of the substring of this DocumentText.</param>
  143. /// <param name="text">The Document text with the substring being compared to.</param>
  144. /// <param name="textOffset">The index of the first character of the substring of the DocumentText being compared to.</param>
  145. /// <param name="length">The number of characters in the substring being compared.</param>
  146. /// <returns></returns>
  147. public bool Equals(int offset, DocumentText text, int textOffset, int length)
  148. { //TODO: (int position, int length, DocumentText text, int textPosition)
  149. if(offset < 0 || length < 0 || offset + length > this.Length) { Debug.Assert(false); return false; }
  150. if(textOffset < 0 || text == null || textOffset + length > text.Length) { Debug.Assert(false); return false; }
  151. unsafe
  152. {
  153. byte* p = this.AsciiStringPtr;
  154. if(p != null)
  155. {
  156. unsafe
  157. {
  158. byte* q = text.AsciiStringPtr;
  159. if(q != null)
  160. {
  161. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  162. if(*(p + i) != *(q + j))
  163. return false;
  164. return true;
  165. }
  166. }
  167. string textSource = text.Source;
  168. if(textSource != null)
  169. {
  170. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  171. if(((char)*(p + i)) != textSource[j])
  172. return false;
  173. return true;
  174. }
  175. ISourceText textProvider = text.TextProvider;
  176. if(textProvider == null) { Debug.Assert(false); return false; }
  177. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  178. if(((char)*(p + i)) != textProvider[j])
  179. return false;
  180. return true;
  181. }
  182. }
  183. string source = this.Source;
  184. if(source != null)
  185. {
  186. unsafe
  187. {
  188. byte* q = text.AsciiStringPtr;
  189. if(q != null)
  190. {
  191. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  192. if(source[i] != (char)*(q + j))
  193. return false;
  194. return true;
  195. }
  196. }
  197. string textSource = text.Source;
  198. if(textSource != null)
  199. {
  200. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  201. if(source[i] != textSource[j])
  202. return false;
  203. return true;
  204. }
  205. ISourceText textProvider = text.TextProvider;
  206. if(textProvider == null) { Debug.Assert(false); return false; }
  207. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  208. if(source[i] != textProvider[j])
  209. return false;
  210. return true;
  211. }
  212. {
  213. ISourceText myProvider = this.TextProvider;
  214. if(myProvider == null) { Debug.Assert(false); return false; }
  215. unsafe
  216. {
  217. byte* q = text.AsciiStringPtr;
  218. if(q != null)
  219. {
  220. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  221. if(myProvider[i] != (char)*(q + j))
  222. return false;
  223. return true;
  224. }
  225. }
  226. string textSource = text.Source;
  227. if(textSource != null)
  228. {
  229. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  230. if(myProvider[i] != textSource[j])
  231. return false;
  232. return true;
  233. }
  234. ISourceText textProvider = text.TextProvider;
  235. if(textProvider == null) { Debug.Assert(false); return false; }
  236. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  237. if(myProvider[i] != textProvider[j])
  238. return false;
  239. return true;
  240. }
  241. }
  242. /// <summary>
  243. /// Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
  244. /// </summary>
  245. public string/*!*/ Substring(int position, int length)
  246. {
  247. if(position < 0 || length < 0 || position + length > this.Length + 1) { Debug.Assert(false); return ""; }
  248. if(position + length > this.Length)
  249. length = this.Length - position; //Allow virtual EOF character to be included in length
  250. if(this.AsciiStringPtr != null)
  251. {
  252. unsafe
  253. {
  254. return new String((sbyte*)this.AsciiStringPtr, position, length, System.Text.Encoding.ASCII);
  255. }
  256. }
  257. else if(this.Source != null)
  258. return this.Source.Substring(position, length);
  259. else if(this.TextProvider != null)
  260. return this.TextProvider.Substring(position, length);
  261. else
  262. {
  263. Debug.Assert(false);
  264. return "";
  265. }
  266. }
  267. /// <summary>
  268. /// Retrieves the character at the given position. The first character is at position zero.
  269. /// </summary>
  270. public char this[int position]
  271. {
  272. get
  273. {
  274. if(position < 0 || position >= this.Length) { Debug.Assert(false); return (char)0; }
  275. if(this.AsciiStringPtr != null)
  276. {
  277. unsafe
  278. {
  279. unchecked
  280. {
  281. return (char)*(this.AsciiStringPtr + position);
  282. }
  283. }
  284. }
  285. else if(this.Source != null)
  286. return this.Source[position];
  287. else if(this.TextProvider != null)
  288. return this.TextProvider[position];
  289. else
  290. {
  291. Debug.Assert(false);
  292. return (char)0;
  293. }
  294. }
  295. }
  296. }
  297. /// <summary>
  298. /// A source document from which an Abstract Syntax Tree has been derived.
  299. /// </summary>
  300. public class Document
  301. {
  302. /// <summary>
  303. /// A Guid that identifies the kind of document to applications such as a debugger. Typically System.Diagnostics.SymbolStore.SymDocumentType.Text.
  304. /// </summary>
  305. public System.Guid DocumentType;
  306. /// <summary>
  307. /// A Guid that identifies the programming language used in the source document. Typically used by a debugger to locate language specific logic.
  308. /// </summary>
  309. public System.Guid Language;
  310. /// <summary>
  311. /// A Guid that identifies the compiler vendor programming language used in the source document. Typically used by a debugger to locate vendor specific logic.
  312. /// </summary>
  313. public System.Guid LanguageVendor;
  314. /// <summary>
  315. /// The line number corresponding to the first character in Text. Typically 1 but can be changed by C# preprocessor directives.
  316. /// </summary>
  317. public int LineNumber;
  318. /// <summary>
  319. /// Indicates that the document contains machine generated source code that should not show up in tools such as debuggers.
  320. /// Can be set by C# preprocessor directives.
  321. /// </summary>
  322. public bool Hidden;
  323. /// <summary>
  324. /// The name of the document. Typically a file name. Can be a full or relative file path, or a URI or some other kind of identifier.
  325. /// </summary>
  326. public string/*!*/ Name;
  327. /// <summary>
  328. /// Contains the source text.
  329. /// </summary>
  330. public DocumentText Text;
  331. public Document()
  332. {
  333. this.Name = "";
  334. //^ base();
  335. }
  336. public Document(string/*!*/ name, int lineNumber, string text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
  337. : this(name, lineNumber, new DocumentText(text), documentType, language, languageVendor)
  338. {
  339. }
  340. public Document(string/*!*/ name, int lineNumber, DocumentText text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
  341. {
  342. this.DocumentType = documentType;
  343. this.Language = language;
  344. this.LanguageVendor = languageVendor;
  345. this.LineNumber = lineNumber;
  346. this.Name = name;
  347. this.Text = text;
  348. //^ base();
  349. }
  350. /// <summary>
  351. /// Maps the given zero based character position to the number of the source line containing the same character.
  352. /// Line number counting starts from the value of LineNumber.
  353. /// </summary>
  354. public virtual int GetLine(int position)
  355. {
  356. int line = 0;
  357. int column = 0;
  358. this.GetPosition(position, out line, out column);
  359. return line + this.LineNumber;
  360. }
  361. /// <summary>
  362. /// Maps the given zero based character position in the entire text to the position of the same character in a source line.
  363. /// Counting within the source line starts at 1.
  364. /// </summary>
  365. public virtual int GetColumn(int position)
  366. {
  367. int line = 0;
  368. int column = 0;
  369. this.GetPosition(position, out line, out column);
  370. return column + 1;
  371. }
  372. /// <summary>
  373. /// Given a startLine, startColum, endLine and endColumn, this returns the corresponding startPos and endPos. In other words it
  374. /// converts a range expression in line and columns to a range expressed as a start and end character position.
  375. /// </summary>
  376. /// <param name="startLine">The number of the line containing the first character. The number of the first line equals this.LineNumber.</param>
  377. /// <param name="startColumn">The position of the first character relative to the start of the line. Counting from 1.</param>
  378. /// <param name="endLine">The number of the line contain the character that immediate follows the last character of the range.</param>
  379. /// <param name="endColumn">The position, in the last line, of the character that immediately follows the last character of the range.</param>
  380. /// <param name="startPos">The position in the entire text of the first character of the range, counting from 0.</param>
  381. /// <param name="endPos">The position in the entire text of the character following the last character of the range.</param>
  382. public virtual void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startPos, out int endPos)
  383. {
  384. lock(this)
  385. {
  386. if(this.lineOffsets == null)
  387. this.ComputeLineOffsets();
  388. //^ assert this.lineOffsets != null;
  389. startPos = this.lineOffsets[startLine - this.LineNumber] + startColumn - 1;
  390. endPos = this.lineOffsets[endLine - this.LineNumber] + endColumn - 1;
  391. }
  392. }
  393. /// <summary>
  394. /// Retrieves a substring from the text of this Document. The substring starts at a specified character position and has a specified length.
  395. /// </summary>
  396. public virtual string Substring(int position, int length)
  397. {
  398. if(this.Text == null)
  399. return null;
  400. return this.Text.Substring(position, length);
  401. }
  402. /// <summary>
  403. /// Counts the number of end of line marker sequences in the given text.
  404. /// </summary>
  405. protected int GetLineCount(string/*!*/ text)
  406. {
  407. int n = text == null ? 0 : text.Length;
  408. int count = 0;
  409. for(int i = 0; i < n; i++)
  410. {
  411. switch(text[i])
  412. {
  413. case '\r':
  414. if(i + 1 < n && text[i + 1] == '\n')
  415. i++;
  416. count++;
  417. break;
  418. case '\n':
  419. case (char)0x2028:
  420. case (char)0x2029:
  421. count++;
  422. break;
  423. }
  424. }
  425. return count;
  426. }
  427. /// <summary>An array of offsets, with offset at index i corresponding to the position of the first character of line i, (counting lines from 0).</summary>
  428. private int[] lineOffsets;
  429. /// <summary>The number of lines in Text.</summary>
  430. private int lines;
  431. /// <summary>
  432. /// Returns the index in this.lineOffsets array such that this.lineOffsets[index] is less than or equal to offset
  433. /// and offset is less than lineOffsets[index+1]
  434. /// </summary>
  435. private int Search(int offset)
  436. {
  437. tryAgain:
  438. int[] lineOffsets = this.lineOffsets;
  439. int lines = this.lines;
  440. if(lineOffsets == null) { Debug.Assert(false); return -1; }
  441. if(offset < 0) { Debug.Assert(false); return -1; }
  442. int mid = 0;
  443. int low = 0;
  444. int high = lines - 1;
  445. while(low < high)
  446. {
  447. mid = (low + high) / 2;
  448. if(lineOffsets[mid] <= offset)
  449. {
  450. if(offset < lineOffsets[mid + 1])
  451. return mid;
  452. else
  453. low = mid + 1;
  454. }
  455. else
  456. high = mid;
  457. }
  458. Debug.Assert(lines == this.lines);
  459. Debug.Assert(lineOffsets[low] <= offset);
  460. Debug.Assert(offset < lineOffsets[low + 1]);
  461. if(lineOffsets != this.lineOffsets)
  462. goto tryAgain;
  463. return low;
  464. }
  465. /// <summary>
  466. /// Maps the given zero based character position in the entire text to a (line, column) pair corresponding to the same position.
  467. /// Counting within the source line starts at 0. Counting source lines start at 0.
  468. /// </summary>
  469. private void GetPosition(int offset, out int line, out int column)
  470. {
  471. line = 0;
  472. column = 0;
  473. if(offset < 0 || this.Text == null || offset > this.Text.Length) { Debug.Assert(false); return; }
  474. lock(this)
  475. {
  476. if(this.lineOffsets == null)
  477. this.ComputeLineOffsets();
  478. if(this.lineOffsets == null) { Debug.Assert(false); return; }
  479. int[] lineOffsets = this.lineOffsets;
  480. int index = this.Search(offset);
  481. Debug.Assert(lineOffsets == this.lineOffsets);
  482. if(index < 0 || index >= this.lineOffsets.Length) { Debug.Assert(false); return; }
  483. Debug.Assert(this.lineOffsets[index] <= offset && offset < this.lineOffsets[index + 1]);
  484. line = index;
  485. column = offset - this.lineOffsets[index];
  486. }
  487. }
  488. /// <summary>
  489. /// Adds the given offset to the this.lineOffsets table as the offset corresponding to the start of line this.lines+1.
  490. /// </summary>
  491. private void AddOffset(int offset)
  492. {
  493. if(this.lineOffsets == null || this.lines < 0) { Debug.Assert(false); return; }
  494. if(this.lines >= this.lineOffsets.Length)
  495. {
  496. int n = this.lineOffsets.Length;
  497. if(n <= 0)
  498. n = 16;
  499. int[] newLineOffsets = new int[n * 2];
  500. Array.Copy(this.lineOffsets, newLineOffsets, this.lineOffsets.Length);
  501. this.lineOffsets = newLineOffsets;
  502. }
  503. this.lineOffsets[this.lines++] = offset;
  504. }
  505. public virtual void InsertOrDeleteLines(int offset, int lineCount)
  506. {
  507. if(lineCount == 0)
  508. return;
  509. if(offset < 0 || this.Text == null || offset > this.Text.Length) { Debug.Assert(false); return; }
  510. lock(this)
  511. {
  512. if(this.lineOffsets == null)
  513. if(this.lineOffsets == null)
  514. this.ComputeLineOffsets();
  515. if(lineCount < 0)
  516. this.DeleteLines(offset, -lineCount);
  517. else
  518. this.InsertLines(offset, lineCount);
  519. }
  520. }
  521. private void DeleteLines(int offset, int lineCount)
  522. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  523. {
  524. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  525. int index = this.Search(offset);
  526. if(index < 0 || index >= this.lines) { Debug.Assert(false); return; }
  527. for(int i = index + 1; i + lineCount < this.lines; i++)
  528. {
  529. this.lineOffsets[i] = this.lineOffsets[i + lineCount];
  530. }
  531. this.lines -= lineCount;
  532. if(this.lines <= index) { Debug.Assert(false); this.lines = index + 1; }
  533. }
  534. private void InsertLines(int offset, int lineCount)
  535. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  536. {
  537. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  538. int index = this.Search(offset);
  539. if(index < 0 || index >= this.lines) { Debug.Assert(false); return; }
  540. int n = this.lineOffsets[this.lines - 1];
  541. for(int i = 0; i < lineCount; i++)
  542. this.AddOffset(++n);
  543. for(int i = lineCount; i > 0; i--)
  544. {
  545. this.lineOffsets[index + i + 1] = this.lineOffsets[index + 1];
  546. }
  547. }
  548. /// <summary>
  549. /// Populates this.lineOffsets with an array of offsets, with offset at index i corresponding to the position of the first
  550. /// character of line i, (counting lines from 0).
  551. /// </summary>
  552. private void ComputeLineOffsets()
  553. //ensures this.lineOffsets != null;
  554. {
  555. if(this.Text == null) { Debug.Assert(false); return; }
  556. int n = this.Text.Length;
  557. this.lineOffsets = new int[n / 10 + 1];
  558. this.lines = 0;
  559. this.AddOffset(0);
  560. for(int i = 0; i < n; i++)
  561. {
  562. switch(this.Text[i])
  563. {
  564. case '\r':
  565. if(i + 1 < n && this.Text[i + 1] == '\n')
  566. i++;
  567. this.AddOffset(i + 1);
  568. break;
  569. case '\n':
  570. case (char)0x2028:
  571. case (char)0x2029:
  572. this.AddOffset(i + 1);
  573. break;
  574. }
  575. }
  576. this.AddOffset(n + 1);
  577. this.AddOffset(n + 2);
  578. }
  579. /// <summary> Add one to this every time a Document instance gets a unique key.</summary>
  580. private static int uniqueKeyCounter;
  581. private int uniqueKey;
  582. /// <summary>
  583. /// An integer that uniquely distinguishes this document instance from every other document instance.
  584. /// This provides an efficient equality test to facilitate hashing.
  585. /// </summary>
  586. public int UniqueKey
  587. {
  588. get
  589. {
  590. if(this.uniqueKey == 0)
  591. {
  592. TryAgain:
  593. int c = Document.uniqueKeyCounter;
  594. int cp1 = c == int.MaxValue ? 1 : c + 1;
  595. if(System.Threading.Interlocked.CompareExchange(ref Document.uniqueKeyCounter, cp1, c) != c)
  596. goto TryAgain;
  597. this.uniqueKey = cp1;
  598. }
  599. return this.uniqueKey;
  600. }
  601. }
  602. }
  603. internal class UnmanagedDocument : Document
  604. {
  605. internal UnmanagedDocument(IntPtr ptrToISymUnmanagedDocument)
  606. {
  607. //^ base();
  608. ISymUnmanagedDocument idoc =
  609. (ISymUnmanagedDocument)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(ptrToISymUnmanagedDocument, typeof(ISymUnmanagedDocument));
  610. if(idoc != null)
  611. {
  612. try
  613. {
  614. idoc.GetDocumentType(out this.DocumentType);
  615. idoc.GetLanguage(out this.Language);
  616. idoc.GetLanguageVendor(out this.LanguageVendor);
  617. uint capacity = 1024;
  618. uint len = 0;
  619. char[] buffer = new char[capacity];
  620. while(capacity >= 1024)
  621. {
  622. idoc.GetURL(capacity, out len, buffer);
  623. if(len < capacity)
  624. break;
  625. capacity += 1024;
  626. buffer = new char[capacity];
  627. }
  628. if(len > 0)
  629. this.Name = new String(buffer, 0, (int)len - 1);
  630. }
  631. finally
  632. {
  633. System.Runtime.InteropServices.Marshal.ReleaseComObject(idoc);
  634. }
  635. }
  636. this.LineNumber = -1;
  637. this.Text = null;
  638. }
  639. private List<int> lineList = new List<int>();
  640. private List<int> columnList = new List<int>();
  641. public override int GetLine(int offset)
  642. {
  643. return this.lineList[offset];
  644. }
  645. public override int GetColumn(int offset)
  646. {
  647. return this.columnList[offset];
  648. }
  649. public override void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startCol, out int endCol)
  650. {
  651. int i = UnmanagedDocument.BinarySearch(this.lineList, startLine);
  652. List<int> columnList = this.columnList;
  653. startCol = 0;
  654. for(int j = i, n = columnList.Count; j < n; j++)
  655. {
  656. if(columnList[j] >= startColumn) { startCol = j; break; }
  657. }
  658. endCol = 0;
  659. i = UnmanagedDocument.BinarySearch(this.lineList, endLine);
  660. for(int j = i, n = columnList.Count; j < n; j++)
  661. {
  662. if(columnList[j] >= endColumn) { endCol = j; break; }
  663. }
  664. }
  665. private static int BinarySearch(List<int> list, int value)
  666. {
  667. int mid = 0;
  668. int low = 0;
  669. int high = list.Count - 1;
  670. while(low < high)
  671. {
  672. mid = low + (high - low) / 2;
  673. if(list[mid] <= value)
  674. {
  675. if(list[mid + 1] > value)
  676. return mid;
  677. else
  678. low = mid + 1;
  679. }
  680. else
  681. high = mid;
  682. }
  683. return low;
  684. }
  685. public override void InsertOrDeleteLines(int offset, int lineCount)
  686. {
  687. Debug.Assert(false); //Caller should not be modifying an unmanaged document
  688. }
  689. internal int GetOffset(uint line, uint column)
  690. {
  691. this.lineList.Add((int)line);
  692. this.columnList.Add((int)column);
  693. return this.lineList.Count - 1;
  694. }
  695. }
  696. /// <summary>
  697. /// Records a location within a source document that corresponds to an Abstract Syntax Tree node.
  698. /// </summary>
  699. public struct SourceContext
  700. {
  701. /// <summary>The source document within which the AST node is located. Null if the node is not derived from a source document.</summary>
  702. public Document Document;
  703. /// <summary>
  704. /// The zero based index of the first character beyond the last character in the source document that corresponds to the AST node.
  705. /// </summary>
  706. public int EndPos;
  707. /// <summary>
  708. /// The zero based index of the first character in the source document that corresponds to the AST node.
  709. /// </summary>
  710. public int StartPos;
  711. public SourceContext(Document document)
  712. : this(document, 0, document == null ? 0 : (document.Text == null ? 0 : document.Text.Length))
  713. {
  714. }
  715. public SourceContext(Document document, int startPos, int endPos)
  716. {
  717. this.Document = document;
  718. this.StartPos = startPos;
  719. this.EndPos = endPos;
  720. }
  721. public SourceContext(Document/*!*/ document,
  722. int startLine, int startColumn, int endLine, int endColumn)
  723. {
  724. this.Document = document;
  725. this.Document.GetOffsets(startLine, startColumn, endLine, endColumn, out this.StartPos, out this.EndPos);
  726. }
  727. /// <summary>
  728. /// The number (counting from Document.LineNumber) of the line containing the first character in the source document that corresponds to the AST node.
  729. /// </summary>
  730. public int StartLine
  731. {
  732. get
  733. {
  734. if(this.Document == null)
  735. return 0;
  736. return this.Document.GetLine(this.StartPos);
  737. }
  738. }
  739. /// <summary>
  740. /// The number (counting from one) of the line column containing the first character in the source document that corresponds to the AST node.
  741. /// </summary>
  742. public int StartColumn
  743. {
  744. get
  745. {
  746. if(this.Document == null)
  747. return 0;
  748. return this.Document.GetColumn(this.StartPos);
  749. }
  750. }
  751. /// <summary>
  752. /// The number (counting from Document.LineNumber) of the line containing the first character beyond the last character in the source document that corresponds to the AST node.
  753. /// </summary>
  754. public int EndLine
  755. {
  756. get
  757. {
  758. if(this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument)))
  759. return 0;
  760. if(this.Document.Text != null && this.EndPos >= this.Document.Text.Length)
  761. this.EndPos = this.Document.Text.Length;
  762. return this.Document.GetLine(this.EndPos);
  763. }
  764. }
  765. /// <summary>
  766. /// The number (counting from one) of the line column containing first character beyond the last character in the source document that corresponds to the AST node.
  767. /// </summary>
  768. public int EndColumn
  769. {
  770. get
  771. {
  772. if(this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument)))
  773. return 0;
  774. if(this.Document.Text != null && this.EndPos >= this.Document.Text.Length)
  775. this.EndPos = this.Document.Text.Length;
  776. return this.Document.GetColumn(this.EndPos);
  777. }
  778. }
  779. /// <summary>
  780. /// Returns true if the line and column is greater than or equal the position of the first character
  781. /// and less than or equal to the position of the last character
  782. /// of the source document that corresponds to the AST node.
  783. /// </summary>
  784. /// <param name="line">A line number(counting from Document.LineNumber)</param>
  785. /// <param name="column">A column number (counting from one)</param>
  786. /// <returns></returns>
  787. public bool Encloses(int line, int column)
  788. {
  789. if(line < this.StartLine || line > this.EndLine)
  790. return false;
  791. if(line == this.StartLine)
  792. return column >= this.StartColumn && (column <= this.EndColumn || line < this.EndLine);
  793. if(line == this.EndLine)
  794. return column <= this.EndColumn;
  795. return true;
  796. }
  797. public bool Encloses(SourceContext sourceContext)
  798. {
  799. return this.StartPos <= sourceContext.StartPos && this.EndPos >= sourceContext.EndPos && this.EndPos > sourceContext.StartPos;
  800. }
  801. /// <summary>
  802. /// The substring of the source document that corresponds to the AST node.
  803. /// </summary>
  804. public string SourceText
  805. {
  806. get
  807. {
  808. if(this.Document == null)
  809. return null;
  810. return this.Document.Substring(this.StartPos, this.EndPos - this.StartPos);
  811. }
  812. }
  813. }
  814. public sealed class MarshallingInformation
  815. {
  816. private string @class;
  817. private string cookie;
  818. private int elementSize;
  819. private NativeType elementType;
  820. private NativeType nativeType;
  821. private int numberOfElements;
  822. private int paramIndex;
  823. private int size;
  824. public MarshallingInformation Clone()
  825. {
  826. return (MarshallingInformation)base.MemberwiseClone();
  827. }
  828. public string Class
  829. {
  830. get { return this.@class; }
  831. set { this.@class = value; }
  832. }
  833. public string Cookie
  834. {
  835. get { return this.cookie; }
  836. set { this.cookie = value; }
  837. }
  838. public int ElementSize
  839. {
  840. get { return this.elementSize; }
  841. set { this.elementSize = value; }
  842. }
  843. public NativeType ElementType
  844. {
  845. get { return this.elementType; }
  846. set { this.elementType = value; }
  847. }
  848. public NativeType NativeType
  849. {
  850. get { return this.nativeType; }
  851. set { this.nativeType = value; }
  852. }
  853. public int NumberOfElements
  854. {
  855. get { return this.numberOfElements; }
  856. set { this.numberOfElements = value; }
  857. }
  858. public int ParamIndex
  859. {
  860. get { return this.paramIndex; }
  861. set { this.paramIndex = value; }
  862. }
  863. public int Size
  864. {
  865. get { return this.size; }
  866. set { this.size = value; }
  867. }
  868. }
  869. public enum NativeType
  870. {
  871. Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
  872. I1 = 0x3, // 1 byte signed value
  873. U1 = 0x4, // 1 byte unsigned value
  874. I2 = 0x5, // 2 byte signed value
  875. U2 = 0x6, // 2 byte unsigned value
  876. I4 = 0x7, // 4 byte signed value
  877. U4 = 0x8, // 4 byte unsigned value
  878. I8 = 0x9, // 8 byte signed value
  879. U8 = 0xa, // 8 byte unsigned value
  880. R4 = 0xb, // 4 byte floating point
  881. R8 = 0xc, // 8 byte floating point
  882. Currency = 0xf, // A currency
  883. BStr = 0x13, // OLE Unicode BSTR
  884. LPStr = 0x14, // Ptr to SBCS string
  885. LPWStr = 0x15, // Ptr to Unicode string
  886. LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
  887. ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs)
  888. IUnknown = 0x19, // COM IUnknown pointer.
  889. IDispatch = 0x1a, // COM IDispatch pointer
  890. Struct = 0x1b, // Structure
  891. Interface = 0x1c, // COM interface
  892. SafeArray = 0x1d, // OLE SafeArray
  893. ByValArray = 0x1e, // Array of fixed size (only valid in structs)
  894. SysInt = 0x1f, // Hardware natural sized signed integer
  895. SysUInt = 0x20,
  896. VBByRefStr = 0x22,
  897. AnsiBStr = 0x23, // OLE BSTR containing SBCS characters
  898. TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR
  899. VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0)
  900. FunctionPtr = 0x26, // Function pointer
  901. AsAny = 0x28, // Paired with Object type and does runtime marshalling determination
  902. LPArray = 0x2a, // C style array
  903. LPStruct = 0x2b, // Pointer to a structure
  904. CustomMarshaler = 0x2c, // Native type supplied by custom code
  905. Error = 0x2d,
  906. NotSpecified = 0x50,
  907. }
  908. ///0-: Common
  909. ///1000-: HScript
  910. ///2000-: EcmaScript
  911. ///3000-: Zonnon
  912. ///4000-: Comega
  913. ///5000-: X++
  914. ///6000-: Spec#
  915. ///7000-: Sing#
  916. ///8000-: Xaml
  917. ///9000-: C/AL
  918. ///For your range contact hermanv@microsoft.com
  919. public enum NodeType
  920. {
  921. //Dummy
  922. Undefined = 0,
  923. //IL instruction node tags
  924. Add,
  925. Add_Ovf,
  926. Add_Ovf_Un,
  927. And,
  928. Arglist,
  929. Box,
  930. Branch,
  931. Call,
  932. Calli,
  933. Callvirt,
  934. Castclass,
  935. Ceq,
  936. Cgt,
  937. Cgt_Un,
  938. Ckfinite,
  939. Clt,
  940. Clt_Un,
  941. Conv_I,
  942. Conv_I1,
  943. Conv_I2,
  944. Conv_I4,
  945. Conv_I8,
  946. Conv_Ovf_I,
  947. Conv_Ovf_I_Un,
  948. Conv_Ovf_I1,
  949. Conv_Ovf_I1_Un,
  950. Conv_Ovf_I2,
  951. Conv_Ovf_I2_Un,
  952. Conv_Ovf_I4,
  953. Conv_Ovf_I4_Un,
  954. Conv_Ovf_I8,
  955. Conv_Ovf_I8_Un,
  956. Conv_Ovf_U,
  957. Conv_Ovf_U_Un,
  958. Conv_Ovf_U1,
  959. Conv_Ovf_U1_Un,
  960. Conv_Ovf_U2,
  961. Conv_Ovf_U2_Un,
  962. Conv_Ovf_U4,
  963. Conv_Ovf_U4_Un,
  964. Conv_Ovf_U8,
  965. Conv_Ovf_U8_Un,
  966. Conv_R_Un,
  967. Conv_R4,
  968. Conv_R8,
  969. Conv_U,
  970. Conv_U1,
  971. Conv_U2,
  972. Conv_U4,
  973. Conv_U8,
  974. Cpblk,
  975. DebugBreak,
  976. Div,
  977. Div_Un,
  978. Dup,
  979. EndFilter,
  980. EndFinally,
  981. ExceptionHandler,
  982. Initblk,
  983. Isinst,
  984. Jmp,
  985. Ldftn,
  986. Ldlen,
  987. Ldtoken,
  988. Ldvirtftn,
  989. Localloc,
  990. Mkrefany,
  991. Mul,
  992. Mul_Ovf,
  993. Mul_Ovf_Un,
  994. Neg,
  995. Nop,
  996. Not,
  997. Or,
  998. Pop,
  999. ReadOnlyAddressOf,
  1000. Refanytype,
  1001. Refanyval,
  1002. Rem,
  1003. Rem_Un,
  1004. Rethrow,
  1005. Shl,
  1006. Shr,
  1007. Shr_Un,
  1008. Sizeof,
  1009. SkipCheck,
  1010. Sub,
  1011. Sub_Ovf,
  1012. Sub_Ovf_Un,
  1013. SwitchInstruction,
  1014. Throw,
  1015. Unbox,
  1016. UnboxAny,
  1017. Xor,
  1018. //AST tags that are relevant to the binary reader
  1019. AddressDereference,
  1020. AddressOf,
  1021. AssignmentStatement,
  1022. Block,
  1023. Catch,
  1024. Construct,
  1025. ConstructArray,
  1026. Eq,
  1027. ExpressionStatement,
  1028. FaultHandler,
  1029. Filter,
  1030. Finally,
  1031. Ge,
  1032. Gt,
  1033. Identifier,
  1034. Indexer,
  1035. Instruction,
  1036. InterfaceExpression,
  1037. Le,
  1038. Literal,
  1039. LogicalNot,
  1040. Lt,
  1041. MemberBinding,
  1042. NamedArgument,
  1043. Namespace,
  1044. Ne,
  1045. Return,
  1046. This,
  1047. Try,
  1048. //Metadata node tags
  1049. ArrayType,
  1050. @Assembly,
  1051. AssemblyReference,
  1052. Attribute,
  1053. Class,
  1054. ClassParameter,
  1055. DelegateNode,
  1056. EnumNode,
  1057. Event,
  1058. Field,
  1059. FunctionPointer,
  1060. InstanceInitializer,
  1061. Interface,
  1062. Local,
  1063. Method,
  1064. Module,
  1065. ModuleReference,
  1066. OptionalModifier,
  1067. Parameter,
  1068. Pointer,
  1069. Property,
  1070. Reference,
  1071. RequiredModifier,
  1072. SecurityAttribute,
  1073. StaticInitializer,
  1074. Struct,
  1075. TypeParameter,
  1076. // The following NodeType definitions are not required
  1077. // for examining assembly metadata directly from binaries
  1078. //Serialization tags used for values that are not leaf nodes.
  1079. Array,
  1080. BlockReference,
  1081. CompilationParameters,
  1082. Document,
  1083. EndOfRecord,
  1084. Expression,
  1085. Guid,
  1086. List,
  1087. MarshallingInformation,
  1088. Member,
  1089. MemberReference,
  1090. MissingBlockReference,
  1091. MissingExpression,
  1092. MissingMemberReference,
  1093. String,
  1094. StringDictionary,
  1095. TypeNode,
  1096. Uri,
  1097. XmlNode,
  1098. //Source-based AST node tags
  1099. AddEventHandler,
  1100. AliasDefinition,
  1101. AnonymousNestedFunction,
  1102. ApplyToAll,
  1103. ArglistArgumentExpression,
  1104. ArglistExpression,
  1105. ArrayTypeExpression,
  1106. As,
  1107. Assertion,
  1108. AssignmentExpression,
  1109. Assumption,
  1110. Base,
  1111. BlockExpression,
  1112. BoxedTypeExpression,
  1113. ClassExpression,
  1114. CoerceTuple,
  1115. CollectionEnumerator,
  1116. Comma,
  1117. Compilation,
  1118. CompilationUnit,
  1119. CompilationUnitSnippet,
  1120. Conditional,
  1121. ConstructDelegate,
  1122. ConstructFlexArray,
  1123. ConstructIterator,
  1124. ConstructTuple,
  1125. Continue,
  1126. CopyReference,
  1127. CurrentClosure,
  1128. Decrement,
  1129. DefaultValue,
  1130. DoWhile,
  1131. Exit,
  1132. ExplicitCoercion,
  1133. ExpressionSnippet,
  1134. FieldInitializerBlock,
  1135. Fixed,
  1136. FlexArrayTypeExpression,
  1137. For,
  1138. ForEach,
  1139. FunctionDeclaration,
  1140. FunctionTypeExpression,
  1141. Goto,
  1142. GotoCase,
  1143. If,
  1144. ImplicitThis,
  1145. Increment,
  1146. InvariantTypeExpression,
  1147. Is,
  1148. LabeledStatement,
  1149. LocalDeclaration,
  1150. LocalDeclarationsStatement,
  1151. Lock,
  1152. LogicalAnd,
  1153. LogicalOr,
  1154. LRExpression,
  1155. MethodCall,
  1156. NameBinding,
  1157. NonEmptyStreamTypeExpression,
  1158. NonNullableTypeExpression,
  1159. NonNullTypeExpression,
  1160. NullableTypeExpression,
  1161. NullCoalesingExpression,
  1162. OutAddress,
  1163. Parentheses,
  1164. PointerTypeExpression,
  1165. PostfixExpression,
  1166. PrefixExpression,
  1167. QualifiedIdentifer,
  1168. RefAddress,
  1169. ReferenceTypeExpression,
  1170. RefTypeExpression,
  1171. RefValueExpression,
  1172. RemoveEventHandler,
  1173. Repeat,
  1174. ResourceUse,
  1175. SetterValue,
  1176. StackAlloc,
  1177. StatementSnippet,
  1178. StreamTypeExpression,
  1179. Switch,
  1180. SwitchCase,
  1181. SwitchCaseBottom,
  1182. TemplateInstance,
  1183. TupleTypeExpression,
  1184. TypeExpression,
  1185. TypeIntersectionExpression,
  1186. TypeMemberSnippet,
  1187. Typeof,
  1188. TypeReference,
  1189. Typeswitch,
  1190. TypeswitchCase,
  1191. TypeUnionExpression,
  1192. UnaryPlus,
  1193. UsedNamespace,
  1194. VariableDeclaration,
  1195. While,
  1196. Yield,
  1197. //Extended metadata node tags
  1198. ConstrainedType,
  1199. TupleType,
  1200. TypeAlias,
  1201. TypeIntersection,
  1202. TypeUnion,
  1203. //Query node tags
  1204. Composition,
  1205. QueryAggregate,
  1206. QueryAlias,
  1207. QueryAll,
  1208. QueryAny,
  1209. QueryAxis,
  1210. QueryCommit,
  1211. QueryContext,
  1212. QueryDelete,
  1213. QueryDifference,
  1214. QueryDistinct,
  1215. QueryExists,
  1216. QueryFilter,
  1217. QueryGeneratedType,
  1218. QueryGroupBy,
  1219. QueryInsert,
  1220. QueryIntersection,
  1221. QueryIterator,
  1222. QueryJoin,
  1223. QueryLimit,
  1224. QueryOrderBy,
  1225. QueryOrderItem,
  1226. QueryPosition,
  1227. QueryProject,
  1228. QueryQuantifiedExpression,
  1229. QueryRollback,
  1230. QuerySelect,
  1231. QuerySingleton,
  1232. QueryTransact,
  1233. QueryTypeFilter,
  1234. QueryUnion,
  1235. QueryUpdate,
  1236. QueryYielder,
  1237. //Contract node tags
  1238. Acquire,
  1239. Comprehension,
  1240. ComprehensionBinding,
  1241. Ensures,
  1242. EnsuresExceptional,
  1243. EnsuresNormal,
  1244. Iff,
  1245. Implies,
  1246. Invariant,
  1247. LogicalEqual,
  1248. LogicalImply,
  1249. Maplet,
  1250. MethodContract,
  1251. Modelfield,
  1252. ModelfieldContract,
  1253. OldExpression,
  1254. Range,
  1255. Read,
  1256. Requires,
  1257. RequiresOtherwise,
  1258. RequiresPlain,
  1259. TypeContract,
  1260. Write,
  1261. //Node tags for explicit modifiers in front-end
  1262. OptionalModifierTypeExpression,
  1263. RequiredModifierTypeExpression,
  1264. //Temporary node tags
  1265. Count,
  1266. Exists,
  1267. ExistsUnique,
  1268. Forall,
  1269. Max,
  1270. Min,
  1271. Product,
  1272. Sum,
  1273. Quantifier,
  1274. }
  1275. [Flags]
  1276. public enum AssemblyFlags
  1277. {
  1278. None = 0x0000,
  1279. PublicKey = 0x0001,
  1280. Library = 0x0002,
  1281. Platform = 0x0004,
  1282. NowPlatform = 0x0006,
  1283. SideBySideCompatible = 0x0000,
  1284. NonSideBySideCompatible = 0x0010,
  1285. NonSideBySideProcess = 0x0020,
  1286. NonSideBySideMachine = 0x0030,
  1287. CompatibilityMask = 0x00F0,
  1288. Retargetable = 0x0100,
  1289. DisableJITcompileOptimizer = 0x4000,
  1290. EnableJITcompileTracking = 0x8000
  1291. }
  1292. public enum AssemblyHashAlgorithm
  1293. {
  1294. None = 0x0000,
  1295. MD5 = 0x8003,
  1296. SHA1 = 0x8004
  1297. }
  1298. [Flags]
  1299. public enum CallingConventionFlags
  1300. {
  1301. Default = 0x0,
  1302. C = 0x1,
  1303. StandardCall = 0x2,
  1304. ThisCall = 0x3,
  1305. FastCall = 0x4,
  1306. VarArg = 0x5,
  1307. ArgumentConvention = 0x7,
  1308. Generic = 0x10,
  1309. HasThis = 0x20,

Large files files are truncated, but you can click here to view the full file