blob: 966d77aa86590e744df704e39bf549997b88ebab [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library dartdoc.cache;
import 'dart:collection';
import 'dart:io';
import 'package:dartdoc/src/tuple.dart';
String _getNewlineChar(String contents) {
if (contents.contains("\r\n")) {
return "\r\n";
} else if (contents.contains("\r")) {
return "\r";
} else {
return "\n";
}
}
SplayTreeMap<int, int> _createLineNumbersMap(String contents) {
var newlineChar = _getNewlineChar(contents);
var offset = 0;
var lineNumber = 0;
var result = new SplayTreeMap<int, int>();
do {
result[offset] = lineNumber;
offset = contents.indexOf(newlineChar, offset + 1);
lineNumber += 1;
} while (offset != -1);
return result;
}
final LineNumberCache lineNumberCache = new LineNumberCache();
// TODO(kevmoo): this could use some testing
class LineNumberCache {
final Map<String, String> __fileContents = <String, String>{};
final Map<String, SplayTreeMap<int, int>> _lineNumbers =
<String, SplayTreeMap<int, int>>{};
int lineNumber(String file, int offset) {
if (offset == 0) {
return 0;
} else {
var lineMap = _lineNumbers.putIfAbsent(
file, () => _createLineNumbersMap(_fileContents(file)));
var lastKey = lineMap.lastKeyBefore(offset);
return lineMap[lastKey];
}
}
Tuple2<int, int> lineAndColumn(String file, int offset) {
if (offset == 0) {
return new Tuple2(0, 0);
} else {
var lineMap = _lineNumbers.putIfAbsent(
file, () => _createLineNumbersMap(_fileContents(file)));
var lastKey = lineMap.lastKeyBefore(offset);
if (lastKey != null) {
return new Tuple2(lineMap[lastKey] + 1, offset - lastKey);
}
}
return null;
}
String _fileContents(String file) =>
__fileContents.putIfAbsent(file, () => new File(file).readAsStringSync());
}