qsharp-lang 1.0.34-dev → 1.1.0-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,127 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import { log } from "./log.js";
4
- // The QSharp compiler returns positions in utf-8 code unit positions (basically a byte[]
5
- // index), however VS Code and Monaco handle positions as utf-16 code unit positions
6
- // (basically JavaScript string index positions). Thus the positions returned from the
7
- // wasm calls needs to be mapped between the two for editor integration.
8
- /**
9
- * @param positions - An array of utf-8 code unit indexes to map to utf-16 code unit indexes
10
- * @param source - The source code to do the mapping on
11
- * @returns An object where the keys are the utf-8 index and the values are the utf-16 index
12
- */
13
- export function mapUtf16UnitsToUtf8Units(positions, source) {
14
- return mapStringIndexes(source, positions, "utf16");
15
- }
16
- /**
17
- * @param positions - An array of utf-8 code unit indexes to map to utf-16 code unit indexes
18
- * @param source - The source code to do the mapping on
19
- * @returns An object where the keys are the utf-8 index and the values are the utf-16 index
20
- */
21
- export function mapUtf8UnitsToUtf16Units(positions, source) {
22
- return mapStringIndexes(source, positions, "utf8");
23
- }
24
- function mapStringIndexes(buffer, indexes, sourceIndexType) {
25
- const result = {};
26
- if (indexes.length === 0)
27
- return result;
28
- // Remove any duplicates by converting to a set and back to an array
29
- const dedupedIndexes = [...new Set(indexes)];
30
- // Do one pass through the string, so ensure the indexes are in ascending order
31
- const sortedIndexes = dedupedIndexes.sort((a, b) => (a < b ? -1 : 1));
32
- // Assume that Rust handles utf-8 correctly in strings, and that the UTF-8 code units
33
- // per Unicode code point are as per the ranges below:
34
- // - 0x000000 to 0x00007F = 1 utf-8 code unit
35
- // - 0x000080 to 0x0007FF = 2 utf-8 code units
36
- // - 0x000800 to 0x00FFFF = 3 utf-8 code units
37
- // - 0x010000 to 0x10FFFF = 4 utf-8 code units
38
- //
39
- // Also assume the string is valid UTF-16 and all characters
40
- // outside the BMP (i.e. > 0xFFFF) are encoded with valid 'surrogate pairs', and
41
- // no other UTF-16 code units in the D800 - DFFF range occur.
42
- // A valid pair must be "high" surrogate (D800–DBFF) then "low" surrogates (DC00–DFFF)
43
- function isValidSurrogatePair(first, second) {
44
- if (first < 0xd800 ||
45
- first > 0xdbff ||
46
- second < 0xdc00 ||
47
- second > 0xdfff) {
48
- return false;
49
- }
50
- return true;
51
- }
52
- let utf16Index = 0;
53
- let utf8Index = 0;
54
- let sourceIndex = 0; // depending on the conversion requested, this will be equal to utf8Index or utf16Index
55
- let targetIndex = 0; // depending on the conversion requested, this will be equal to utf8Index or utf16Index
56
- let posArrayIndex = 0;
57
- let nextIndex = sortedIndexes[posArrayIndex];
58
- for (;;) {
59
- // Walk though the string, maintaining a UTF-8 to UTF-16 code unit index mapping.
60
- // When the string index >= the next searched for index, save that result and increment.
61
- // If the end of string or end of searched for indexes is reached, then break.
62
- if (sourceIndex >= nextIndex) {
63
- result[sourceIndex] = targetIndex;
64
- if (++posArrayIndex >= sortedIndexes.length)
65
- break;
66
- nextIndex = sortedIndexes[posArrayIndex];
67
- }
68
- if (utf16Index >= buffer.length)
69
- break;
70
- // Get the code unit (not code point) at the string index.
71
- const utf16CodeUnit = buffer.charCodeAt(utf16Index);
72
- // Advance the utf-8 index by the correct amount for the utf-16 code unit value.
73
- if (utf16CodeUnit < 0x80) {
74
- utf8Index += 1;
75
- }
76
- else if (utf16CodeUnit < 0x800) {
77
- utf8Index += 2;
78
- }
79
- else if (utf16CodeUnit < 0xd800 || utf16CodeUnit > 0xdfff) {
80
- // Not a surrogate pair, so one utf-16 code unit over 0x7FF == three utf-8 code utits
81
- utf8Index += 3;
82
- }
83
- else {
84
- // Need to consume the extra utf16 code unit for the pair also.
85
- const nextCodeUnit = buffer.charCodeAt(++utf16Index) || 0;
86
- if (!isValidSurrogatePair(utf16CodeUnit, nextCodeUnit))
87
- throw "Invalid surrogate pair";
88
- // Valid utf-16 surrogate pair implies code point over 0xFFFF implies 4 utf-8 code units.
89
- utf8Index += 4;
90
- }
91
- ++utf16Index; // Don't break here if EOF. We need to handle EOF being the final position to resolve.
92
- sourceIndex = sourceIndexType === "utf8" ? utf8Index : utf16Index;
93
- targetIndex = sourceIndexType === "utf8" ? utf16Index : utf8Index;
94
- }
95
- // TODO: May want to have a more configurable error reporting at some point. Avoid throwing here,
96
- // and just report and continue.
97
- if (posArrayIndex < sortedIndexes.length) {
98
- log.error(`Failed to map all ${sourceIndexType} indexes. Remaining indexes are: ${sortedIndexes.slice(posArrayIndex)}`);
99
- }
100
- return result;
101
- }
102
- export function mapDiagnostics(diags, code) {
103
- // Get a map of the Rust source positions to the JavaScript source positions
104
- const positions = [];
105
- diags.forEach((diag) => {
106
- positions.push(diag.start_pos);
107
- positions.push(diag.end_pos);
108
- diag.related?.forEach((related) => {
109
- positions.push(related.start_pos);
110
- positions.push(related.end_pos);
111
- });
112
- });
113
- const positionMap = mapUtf8UnitsToUtf16Units(positions, code);
114
- // Return the diagnostics with the positions mapped (or EOF if couldn't resolve)
115
- const results = diags.map((diag) => ({
116
- ...diag,
117
- // The mapped position may well be 0, so need to use ?? rather than ||
118
- start_pos: positionMap[diag.start_pos] ?? code.length,
119
- end_pos: positionMap[diag.end_pos] ?? code.length,
120
- related: diag.related?.map((related) => ({
121
- ...related,
122
- start_pos: positionMap[related.start_pos] ?? code.length,
123
- end_pos: positionMap[related.end_pos] ?? code.length,
124
- })),
125
- }));
126
- return results;
127
- }