-
Notifications
You must be signed in to change notification settings - Fork 29
/
HaxePosition.hx
101 lines (92 loc) · 3.68 KB
/
HaxePosition.hx
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
import vscode.BasicTypes.Location;
class HaxePosition {
static var positionRe = ~/^(.+):(\d+): (?:lines (\d+)-(\d+)|character(?:s (\d+)-| )(\d+))$/;
static var properFileNameCaseCache:Map<String,String>;
static var isWindows = (Sys.systemName() == "Windows");
public static function parse(pos:String, doc:TextDocument, cache:Map<String,Array<String>>):Null<Location> {
if (!positionRe.match(pos))
return null;
var file = getProperFileNameCase(positionRe.matched(1));
var s = positionRe.matched(3);
if (s != null) { // line span
var startLine = Std.parseInt(s);
var endLine = Std.parseInt(positionRe.matched(4));
return {
uri: if (file == doc.fsPath) doc.uri else Uri.fsPathToUri(file),
range: {
start: {line: startLine - 1, character: 0},
end: {line: endLine - 1, character: 0},
}
};
} else { // char span
var line = Std.parseInt(positionRe.matched(2));
line--;
var lineContent, uri;
if (file == doc.fsPath) {
// it's a stdin file, we have its content in memory
lineContent = doc.lineAt(line);
uri = doc.uri;
} else {
// we have to read lines from a file on disk (cache if available)
var lines;
if (cache == null) {
lines = sys.io.File.getContent(file).split("\n");
} else {
lines = cache[file];
if (lines == null)
lines = cache[file] = sys.io.File.getContent(file).split("\n");
}
lineContent = lines[line];
uri = Uri.fsPathToUri(file);
}
var endByte = Std.parseInt(positionRe.matched(6));
var endChar = byteOffsetToCharacterOffset(lineContent, endByte);
s = positionRe.matched(5);
var startChar;
if (s != null) {
var startByte = Std.parseInt(s);
startChar = byteOffsetToCharacterOffset(lineContent, startByte);
} else {
startChar = endChar;
}
return {
uri: uri,
range: {
start: {line: line, character: startChar},
end: {line: line, character: endChar},
}
};
}
}
public static inline function byteOffsetToCharacterOffset(string:String, byteOffset:Int):Int {
var buf = new js.node.Buffer(string, "utf-8");
return buf.toString("utf-8", 0, byteOffset).length;
}
static function getProperFileNameCase(normalizedPath:String):String {
if (!isWindows) return normalizedPath;
if (properFileNameCaseCache == null) {
properFileNameCaseCache = new Map();
} else {
var cached = properFileNameCaseCache[normalizedPath];
if (cached != null)
return cached;
}
var result = normalizedPath;
var parts = normalizedPath.split("\\");
if (parts.length > 1) {
var acc = parts[0];
for (i in 1...parts.length) {
var part = parts[i];
for (realFile in sys.FileSystem.readDirectory(acc)) {
if (realFile.toLowerCase() == part) {
part = realFile;
break;
}
}
acc = acc + "/" + part;
}
result = acc;
}
return properFileNameCaseCache[normalizedPath] = result;
}
}