public static int CompareByOriginalPositions(MappingItemIndexed x, MappingItemIndexed y, bool onlyCompareOriginal) { var cmp = x.Source ?? 0 - y.Source ?? 0; if (cmp != 0) { return(cmp); } cmp = x.OriginalLine ?? 0 - y.OriginalLine ?? 0; if (cmp != 0) { return(cmp); } cmp = x.OriginalColumn ?? 0 - y.OriginalColumn ?? 0; if (cmp != 0 || onlyCompareOriginal) { return(cmp); } cmp = x.GeneratedColumn - y.GeneratedColumn; if (cmp != 0) { return(cmp); } cmp = x.GeneratedLine - y.GeneratedLine; if (cmp != 0) { return(cmp); } return(x.Name ?? 0 - y.Name ?? 0); }
/** * Returns the original source, line, and column information for the generated * source's line and column positions provided. The only argument is an object * with the following properties: * * - line: The line number in the generated source. * - column: The column number in the generated source. * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the * closest element that is smaller than or greater than the one we are * searching for, respectively, if the exact element cannot be found. * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. * * and an object is returned with the following properties: * * - source: The original source file, or null. * - line: The line number in the original source, or null. * - column: The column number in the original source, or null. * - name: The original identifier, or null. */ public override OriginalPosition OriginalPositionFor(int line, int column, EBias?bias = null) { var needle = new MappingItemIndexed { GeneratedLine = line, GeneratedColumn = column }; var index = FindMapping( needle, GeneratedMappings, x => x.GeneratedLine, x => x.GeneratedColumn, Util.CompareByGeneratedPositionsDeflated, bias ?? EBias.GREATEST_LOWER_BOUND); if (index >= 0) { var mapping = GeneratedMappings[index]; if (mapping.GeneratedLine == needle.GeneratedLine) { var sourceIndex = mapping.Source; string source = null; if (sourceIndex != null) { source = _sources.At((int)sourceIndex); if (SourceRoot != null) { source = Util.Join(SourceRoot, source); } } var nameIndex = mapping.Name; string name = null; if (nameIndex != null) { name = _names.At((int)nameIndex); } return(new OriginalPosition { Source = source, Line = mapping.OriginalLine, Column = mapping.OriginalColumn, Name = name }); } } return(new OriginalPosition { Source = null, Line = null, Column = null, Name = null }); }
/** * Returns the generated line and column information for the original source, * line, and column positions provided. The only argument is an object with * the following properties: * * - source: The filename of the original source. * - line: The line number in the original source. * - column: The column number in the original source. * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the * closest element that is smaller than or greater than the one we are * searching for, respectively, if the exact element cannot be found. * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. * * and an object is returned with the following properties: * * - line: The line number in the generated source, or null. * - column: The column number in the generated source, or null. */ public override Position GeneratedPositionFor(string source, int line, int column, EBias?bias = null) { if (SourceRoot != null) { source = Util.Relative(SourceRoot, source); } if (!_sources.Has(source)) { return(new Position { Line = null, Column = null, LastColumn = null }); } var sourceIndex = _sources.IndexOf(source); var needle = new MappingItemIndexed { Source = sourceIndex, OriginalLine = line, OriginalColumn = column }; var index = FindMapping( needle, OriginalMappings, x => x.OriginalLine, x => x.OriginalColumn, Util.CompareByOriginalPositions, bias ?? EBias.GREATEST_LOWER_BOUND); if (index >= 0) { var mapping = _originalMappings[index]; if (mapping.Source == needle.Source) { return(new Position { Line = mapping.GeneratedLine, Column = mapping.GeneratedColumn, LastColumn = mapping.LastGeneratedColumn }); } } return(new Position { Line = null, Column = null, LastColumn = null }); }
/** * Parse the mappings in a string in to a data structure which we can easily * query (the ordered arrays in the `this.__generatedMappings` and * `this.__originalMappings` properties). */ protected override void ParseMappings(string aStr, string aSourceRoot) { _generatedMappings = new List <MappingItemIndexed>(); _originalMappings = new List <MappingItemIndexed>(); foreach (var section in _sections) { var sectionMappings = section.Consumer.GeneratedMappings; foreach (var mapping in sectionMappings) { var source = section.Consumer.SourcesSet.At((int)mapping.Source); if (section.Consumer.SourceRoot != null) { source = Util.Join(section.Consumer.SourceRoot, source); } _sources.Add(source, false); var sourceIndex = _sources.IndexOf(source); var name = section.Consumer.NamesSet.At((int)mapping.Name); _names.Add(name, false); var nameIndex = _names.IndexOf(name); // The mappings coming from the consumer for the section have // generated positions relative to the start of the section, so we // need to offset them to be relative to the start of the concatenated // generated file. var adjustedMapping = new MappingItemIndexed { Source = sourceIndex, GeneratedLine = mapping.GeneratedLine + (section.GeneratedOffset.GeneratedLine - 1), GeneratedColumn = mapping.GeneratedColumn + (section.GeneratedOffset.GeneratedLine == mapping.GeneratedLine ? section.GeneratedOffset.GeneratedColumn - 1 : 0), OriginalLine = mapping.OriginalLine, OriginalColumn = mapping.OriginalColumn, Name = nameIndex }; _generatedMappings.Add(adjustedMapping); if (adjustedMapping.OriginalLine != null) { _originalMappings.Add(adjustedMapping); } } } _generatedMappings.Sort((Comparison <MappingItemIndexed>)Util.CompareByGeneratedPositionsDeflated); _originalMappings.Sort((Comparison <MappingItemIndexed>)Util.CompareByOriginalPositions); }
/** * Returns the original source, line, and column information for the generated * source's line and column positions provided. The only argument is an object * with the following properties: * * - line: The line number in the generated source. * - column: The column number in the generated source. * * and an object is returned with the following properties: * * - source: The original source file, or null. * - line: The line number in the original source, or null. * - column: The column number in the original source, or null. * - name: The original identifier, or null. */ public override OriginalPosition OriginalPositionFor(int line, int column, EBias?bias = null) { var needle = new MappingItemIndexed { GeneratedLine = line, GeneratedColumn = column }; // Find the section containing the generated position we're trying to map // to an original position. var sectionIndex = BinarySearch.Search( needle, _sections, (n, s) => { var cmp = n.GeneratedLine - s.GeneratedOffset.GeneratedLine; if (cmp == 0) { return(cmp); } return(n.GeneratedColumn - s.GeneratedOffset.GeneratedColumn); }, EBias.GREATEST_LOWER_BOUND); var section = _sections[sectionIndex]; if (section == null) { return(new OriginalPosition { Source = null, Line = null, Column = null, Name = null }); } return(section.Consumer.OriginalPositionFor( needle.GeneratedLine - (section.GeneratedOffset.GeneratedLine - 1), needle.GeneratedColumn - (section.GeneratedOffset.GeneratedLine == needle.GeneratedLine ? section.GeneratedOffset.GeneratedColumn - 1 : 0), bias)); }
/** * Find the mapping that best matches the hypothetical "needle" mapping that * we are searching for in the given "haystack" of mappings. */ protected int FindMapping( MappingItemIndexed needle, List <MappingItemIndexed> aMappings, Func <MappingItemIndexed, int?> line, Func <MappingItemIndexed, int?> column, Func <MappingItemIndexed, MappingItemIndexed, int> aComparator, EBias aBias) { // To return the position we are searching for, we must first find the // mapping for the given position and then return the opposite position it // points to. Because the mappings are sorted, we can use binary search to // find the best mapping. if (line(needle) <= 0) { throw new ArgumentException($"Line must be greater than or equal to 1, got {line(needle)}"); } if (column(needle) < 0) { throw new ArgumentException($"Column must be greater than or equal to 0, got {column(needle)}"); } return(BinarySearch.Search <MappingItemIndexed>(needle, aMappings, aComparator, aBias)); }
/** * Returns all generated line and column information for the original source, * line, and column provided. If no column is provided, returns all mappings * corresponding to a either the line we are searching for or the next * closest line that has any mappings. Otherwise, returns all mappings * corresponding to the given line and either the column we are searching for * or the next closest column that has any offsets. * * The only argument is an object with the following properties: * * - source: The filename of the original source. * - line: The line number in the original source. * - column: Optional. the column number in the original source. * * and an array of objects is returned, each with the following properties: * * - line: The line number in the generated source, or null. * - column: The column number in the generated source, or null. */ public IEnumerable <Position> AllGeneratedPositionsFor(string source, int line, int?column) { // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping // returns the index of the closest mapping less than the needle. By // setting needle.originalColumn to 0, we thus find the last mapping for // the given line, provided such a mapping exists. var relativeSource = SourceRoot == null ? source : Util.Relative(SourceRoot, source); if (!_sources.Has(relativeSource)) { return(new Position[0]); } var needle = new MappingItemIndexed { Source = _sources.IndexOf(relativeSource), OriginalLine = line, OriginalColumn = column ?? 0 }; var mappings = new List <Position>(); int index = FindMapping(needle, OriginalMappings, x => x.OriginalLine, x => x.OriginalColumn, Util.CompareByOriginalPositions, EBias.LEAST_UPPER_BOUND); if (index < 0) { return(new Position[0]); } { var mapping = OriginalMappings[index]; if (column == null) { var originalLine = mapping.OriginalLine; // Iterate until either we run out of mappings, or we run into // a mapping for a different line than the one we found. Since // mappings are sorted, this is guaranteed to find all mappings for // the line we found. while (mapping != null && mapping.OriginalLine == originalLine) { mappings.Add(new Position { Line = mapping.GeneratedLine, Column = mapping.GeneratedColumn, LastColumn = mapping.LastGeneratedColumn }); mapping = OriginalMappings[++index]; } } else { var originalColumn = mapping.OriginalColumn; // Iterate until either we run out of mappings, or we run into // a mapping for a different line than the one we were searching for. // Since mappings are sorted, this is guaranteed to find all mappings for // the line we are searching for. while (mapping != null && mapping.OriginalLine == line && mapping.OriginalColumn == originalColumn) { mappings.Add(new Position { Line = mapping.GeneratedLine, Column = mapping.GeneratedColumn, LastColumn = mapping.LastGeneratedColumn }); mapping = OriginalMappings[++index]; } } } return(mappings); }
//public BasicSourceMapConsumer(SourceMapGenerator sourceMap) //{ // var names = _names = new ArraySet(sourceMap.Names.ToArray(), true); // var sources = _sources = new ArraySet(sourceMap.Sources.ToArray(), true); // SourceRoot = sourceMap.SourceRoot; // SourcesContent = sourceMap._generateSourcesContent(_sources.ToArray(), SourceRoot); // File = sourceMap.File; // // Because we are modifying the entries (by converting string sources and // // names to indices into the sources and names ArraySets), we have to make // // a copy of the entry or else bad things happen. Shared mutable state // // strikes again! See github issue #191. // var generatedMappings = sourceMap.Mappings.ToArray().slice(); // var destGeneratedMappings = _generatedMappings = new List<MappingItemIndexed>(); // var destOriginalMappings = _originalMappings = new List<MappingItemIndexed>(); // for (int i = 0, length = generatedMappings.Length; i < length; i++) // { // var srcMapping = generatedMappings[i]; // var destMapping = new MappingItemIndexed(); // destMapping.GeneratedLine = srcMapping.GeneratedLine; // destMapping.GeneratedColumn = srcMapping.GeneratedColumn; // if (srcMapping.Source != null) // { // destMapping.Source = sources.IndexOf(srcMapping.Source); // destMapping.OriginalLine = srcMapping.OriginalLine; // destMapping.OriginalColumn = srcMapping.OriginalColumn; // if (srcMapping.Name != null) // destMapping.Name = names.IndexOf(srcMapping.Name); // destOriginalMappings.Add(destMapping); // } // destGeneratedMappings.Add(destMapping); // } // quickSort(_originalMappings, Util.CompareByOriginalPositions); //} //public static ISourceMapConsumer FromSourceMap(SourceMapGenerator sourceMap) //{ // return new BasicSourceMapConsumer(sourceMap); //} /** * Parse the mappings in a string in to a data structure which we can easily * query (the ordered arrays in the `this.__generatedMappings` and * `this.__originalMappings` properties). */ protected override void ParseMappings(string aStr, string aSourceRoot) { var generatedLine = 1; var previousGeneratedColumn = 0; var previousOriginalLine = 0; var previousOriginalColumn = 0; var previousSource = 0; var previousName = 0; var length = aStr.Length; var index = 0; var cachedSegments = new Dictionary <string, List <int> >(); var originalMappings = new List <MappingItemIndexed>(); var generatedMappings = new List <MappingItemIndexed>(); while (index < length) { if (aStr[index] == ';') { generatedLine++; index++; previousGeneratedColumn = 0; } else if (aStr[index] == ',') { index++; } else { var mapping = new MappingItemIndexed(); mapping.GeneratedLine = generatedLine; // Because each offset is encoded relative to the previous one, // many segments often have the same encoding. We can exploit this // fact by caching the parsed variable length fields of each segment, // allowing us to avoid a second parse if we encounter the same // segment again. int end; for (end = index; end < length; end++) { if (CharIsMappingSeparator(aStr, end)) { break; } } var str = aStr.Substring(index, end - index); List <int> segment; if (cachedSegments.ContainsKey(str)) { segment = cachedSegments[str]; index += str.Length; } else { segment = new List <int>(); while (index < end) { int value; Base64Vlq.Decode(aStr, ref index, out value); segment.Add(value); } if (segment.Count == 2) { throw new Exception("Found a source, but no line and column"); } if (segment.Count == 3) { throw new Exception("Found a source and line, but no column"); } cachedSegments.Add(str, segment); } // Generated column. mapping.GeneratedColumn = previousGeneratedColumn + segment[0]; previousGeneratedColumn = mapping.GeneratedColumn; if (segment.Count > 1) { // Original source. mapping.Source = previousSource + segment[1]; previousSource += segment[1]; // Original line. mapping.OriginalLine = previousOriginalLine + segment[2]; previousOriginalLine = (int)mapping.OriginalLine; // Lines are stored 0-based mapping.OriginalLine += 1; // Original column. mapping.OriginalColumn = previousOriginalColumn + segment[3]; previousOriginalColumn = (int)mapping.OriginalColumn; if (segment.Count > 4) { // Original name. mapping.Name = previousName + segment[4]; previousName += segment[4]; } } generatedMappings.Add(mapping); if (mapping.OriginalLine != null) { originalMappings.Add(mapping); } } } generatedMappings.Sort((Comparison <MappingItemIndexed>)Util.CompareByGeneratedPositionsDeflated); _generatedMappings = generatedMappings; originalMappings.Sort((Comparison <MappingItemIndexed>)Util.CompareByOriginalPositions); _originalMappings = originalMappings; }
public static int CompareByOriginalPositions(MappingItemIndexed x, MappingItemIndexed y) { return(CompareByOriginalPositions(x, y, true)); }
public static int CompareByGeneratedPositionsDeflated(MappingItemIndexed x, MappingItemIndexed y) { return(CompareByGeneratedPositionsDeflated(x, y, true)); }