mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 01:30:10 +08:00
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com> Co-authored-by: Henry Mercer <henrymercer@github.com>
250 lines
9.7 KiB
JavaScript
250 lines
9.7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.FileDescriptorProtoFields = exports.makeSourceCodePathComponent = exports.makeSourceCodePath = exports.filterSourceCodeLocations = exports.sourceCodeLocationToComment = exports.sourceCodeLocationToCursor = exports.SourceCodeInfoLookup = void 0;
|
|
const descriptor_1 = require("./google/protobuf/descriptor");
|
|
const runtime_1 = require("@protobuf-ts/runtime");
|
|
class SourceCodeInfoLookup {
|
|
constructor(parentResolver) {
|
|
this._parentResolver = parentResolver;
|
|
}
|
|
sourceCodeCursor(descriptor) {
|
|
var _a, _b;
|
|
const path = makeSourceCodePath(x => this._parentResolver(x), descriptor);
|
|
runtime_1.assert(path !== undefined, `Cannot create source code path`);
|
|
const all = (_b = (_a = this._findFile(descriptor).sourceCodeInfo) === null || _a === void 0 ? void 0 : _a.location) !== null && _b !== void 0 ? _b : [];
|
|
const hit = filterSourceCodeLocations(all, path);
|
|
return sourceCodeLocationToCursor(hit);
|
|
}
|
|
sourceCodeComments(descriptorOrFile, fileDescriptorFieldNumber) {
|
|
var _a, _b;
|
|
const path = makeSourceCodePath(x => this._parentResolver(x), descriptorOrFile);
|
|
runtime_1.assert(path !== undefined, `Cannot create source code path`);
|
|
if (fileDescriptorFieldNumber !== undefined) {
|
|
path.push(fileDescriptorFieldNumber);
|
|
}
|
|
const all = (_b = (_a = this._findFile(descriptorOrFile).sourceCodeInfo) === null || _a === void 0 ? void 0 : _a.location) !== null && _b !== void 0 ? _b : [];
|
|
const hit = filterSourceCodeLocations(all, path);
|
|
return sourceCodeLocationToComment(hit);
|
|
}
|
|
_findFile(d) {
|
|
let c = d;
|
|
while (c) {
|
|
if (descriptor_1.FileDescriptorProto.is(c)) {
|
|
return c;
|
|
}
|
|
c = this._parentResolver(c);
|
|
}
|
|
runtime_1.assert(false);
|
|
}
|
|
}
|
|
exports.SourceCodeInfoLookup = SourceCodeInfoLookup;
|
|
/**
|
|
* Return cursor position of the given source code location
|
|
* as line number and column, both starting at 1.
|
|
*
|
|
* If more than one location is given, only the first one
|
|
* is evaluated, the others are discarded.
|
|
*/
|
|
function sourceCodeLocationToCursor(locations) {
|
|
if (locations.length === 0) {
|
|
return emptyCursor;
|
|
}
|
|
const span = locations[0].span;
|
|
if (span === undefined || span.length < 3 || span.length > 4) {
|
|
return emptyCursor;
|
|
}
|
|
return [
|
|
span[0] + 1,
|
|
span[1] + 1
|
|
];
|
|
}
|
|
exports.sourceCodeLocationToCursor = sourceCodeLocationToCursor;
|
|
const emptyCursor = [undefined, undefined];
|
|
/**
|
|
* Return the comments for the given source code location.
|
|
*
|
|
* If more than one location is given, only the first one
|
|
* is evaluated, the others are discarded.
|
|
*
|
|
* If no comments found, empty (not undefined) object
|
|
* is returned.
|
|
*
|
|
* Trailing newlines are removed.
|
|
*/
|
|
function sourceCodeLocationToComment(locations) {
|
|
if (locations.length === 0) {
|
|
return emptyComment;
|
|
}
|
|
const location = locations[0], leadingDetached = location.leadingDetachedComments.map(stripTrailingNewline), leadingComments = location.leadingComments, leading = leadingComments === ''
|
|
? undefined
|
|
: (leadingComments === undefined
|
|
? undefined
|
|
: stripTrailingNewline(leadingComments)), trailingComments = location.trailingComments, trailing = trailingComments === ''
|
|
? undefined
|
|
: (trailingComments === undefined
|
|
? undefined
|
|
: stripTrailingNewline(trailingComments));
|
|
return (leadingDetached.length === 0 && leading === undefined && trailing === undefined)
|
|
? emptyComment
|
|
: { leadingDetached, leading, trailing };
|
|
}
|
|
exports.sourceCodeLocationToComment = sourceCodeLocationToComment;
|
|
function stripTrailingNewline(block) {
|
|
return block.endsWith('\n')
|
|
? block.slice(0, -1)
|
|
: block;
|
|
}
|
|
const emptyComment = {
|
|
leadingDetached: [],
|
|
leading: undefined,
|
|
trailing: undefined,
|
|
};
|
|
/**
|
|
* Find the source code locations that match the given path.
|
|
*/
|
|
function filterSourceCodeLocations(locations, path) {
|
|
return locations.filter(l => {
|
|
const p = l.path;
|
|
if (p.length !== path.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < p.length; i++) {
|
|
if (p[i] !== path[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
exports.filterSourceCodeLocations = filterSourceCodeLocations;
|
|
/**
|
|
* Create the path to the source code location where the
|
|
* given element was declared.
|
|
*
|
|
* Returns `undefined` if we don't know how to make the path.
|
|
*
|
|
* For example, the path [4, 0, 2, 3] points to the 4th field
|
|
* of the first message of a .proto file:
|
|
*
|
|
* file
|
|
* .messageType // FileDescriptorProto.message_type = 3;
|
|
* [0] // first message
|
|
* .field // FileDescriptorProto.field = 2;
|
|
* [3] // 4th field
|
|
*
|
|
* See https://github.com/protocolbuffers/protobuf/blob/f1ce8663ac88df54cf212d29ce5123b69203b135/src/google/protobuf/descriptor.proto#L799
|
|
*/
|
|
function makeSourceCodePath(parentProvider, descriptor) {
|
|
const path = [];
|
|
let parent = parentProvider(descriptor);
|
|
let component;
|
|
while (parent) {
|
|
component = makeSourceCodePathComponent(parent, descriptor);
|
|
if (component === undefined) {
|
|
return undefined;
|
|
}
|
|
path.unshift(...component);
|
|
descriptor = parent;
|
|
parent = parentProvider(parent);
|
|
}
|
|
return path;
|
|
}
|
|
exports.makeSourceCodePath = makeSourceCodePath;
|
|
/**
|
|
* Make a path from the parent to the immediate child.
|
|
*
|
|
* Returns `undefined` if we don't know how to make the path.
|
|
*/
|
|
function makeSourceCodePathComponent(parent, child) {
|
|
if (descriptor_1.FileDescriptorProto.is(parent) && descriptor_1.DescriptorProto.is(child)) {
|
|
return [
|
|
FileDescriptorProtoFields.message_type,
|
|
parent.messageType.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.FileDescriptorProto.is(parent) && descriptor_1.EnumDescriptorProto.is(child)) {
|
|
return [
|
|
FileDescriptorProtoFields.enum_type,
|
|
parent.enumType.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.FileDescriptorProto.is(parent) && descriptor_1.ServiceDescriptorProto.is(child)) {
|
|
return [
|
|
FileDescriptorProtoFields.service,
|
|
parent.service.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.DescriptorProto.is(parent) && descriptor_1.EnumDescriptorProto.is(child)) {
|
|
return [
|
|
DescriptorProtoFields.enum_type,
|
|
parent.enumType.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.DescriptorProto.is(parent) && descriptor_1.DescriptorProto.is(child)) {
|
|
return [
|
|
DescriptorProtoFields.nested_type,
|
|
parent.nestedType.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.DescriptorProto.is(parent) && descriptor_1.FieldDescriptorProto.is(child)) {
|
|
return [
|
|
DescriptorProtoFields.field,
|
|
parent.field.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.DescriptorProto.is(parent) && descriptor_1.OneofDescriptorProto.is(child)) {
|
|
return [
|
|
DescriptorProtoFields.oneof_decl,
|
|
parent.oneofDecl.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.EnumDescriptorProto.is(parent) && descriptor_1.EnumValueDescriptorProto.is(child)) {
|
|
return [
|
|
EnumDescriptorProtoFields.value,
|
|
parent.value.indexOf(child)
|
|
];
|
|
}
|
|
if (descriptor_1.ServiceDescriptorProto.is(parent) && descriptor_1.MethodDescriptorProto.is(child)) {
|
|
return [
|
|
ServiceDescriptorProtoFields.method,
|
|
parent.method.indexOf(child)
|
|
];
|
|
}
|
|
return undefined;
|
|
}
|
|
exports.makeSourceCodePathComponent = makeSourceCodePathComponent;
|
|
var FileDescriptorProtoFields;
|
|
(function (FileDescriptorProtoFields) {
|
|
FileDescriptorProtoFields[FileDescriptorProtoFields["syntax"] = 12] = "syntax";
|
|
FileDescriptorProtoFields[FileDescriptorProtoFields["package"] = 2] = "package";
|
|
FileDescriptorProtoFields[FileDescriptorProtoFields["message_type"] = 4] = "message_type";
|
|
FileDescriptorProtoFields[FileDescriptorProtoFields["enum_type"] = 5] = "enum_type";
|
|
FileDescriptorProtoFields[FileDescriptorProtoFields["service"] = 6] = "service";
|
|
})(FileDescriptorProtoFields = exports.FileDescriptorProtoFields || (exports.FileDescriptorProtoFields = {}));
|
|
var DescriptorProtoFields;
|
|
(function (DescriptorProtoFields) {
|
|
DescriptorProtoFields[DescriptorProtoFields["field"] = 2] = "field";
|
|
DescriptorProtoFields[DescriptorProtoFields["nested_type"] = 3] = "nested_type";
|
|
DescriptorProtoFields[DescriptorProtoFields["enum_type"] = 4] = "enum_type";
|
|
DescriptorProtoFields[DescriptorProtoFields["options"] = 7] = "options";
|
|
DescriptorProtoFields[DescriptorProtoFields["oneof_decl"] = 8] = "oneof_decl";
|
|
})(DescriptorProtoFields || (DescriptorProtoFields = {}));
|
|
// enum FieldDescriptorProtoFields {
|
|
// name = 1, // optional string name = 1;
|
|
// number = 3, // optional int32 number = 3;
|
|
// label = 4, // optional Label label = 4;
|
|
// type = 5, // optional Type type = 5;
|
|
// }
|
|
var EnumDescriptorProtoFields;
|
|
(function (EnumDescriptorProtoFields) {
|
|
// name = 1, // optional string name = 1;
|
|
EnumDescriptorProtoFields[EnumDescriptorProtoFields["value"] = 2] = "value";
|
|
// options = 3, // optional EnumOptions options = 3;
|
|
})(EnumDescriptorProtoFields || (EnumDescriptorProtoFields = {}));
|
|
var ServiceDescriptorProtoFields;
|
|
(function (ServiceDescriptorProtoFields) {
|
|
// name = 1, // optional string name = 1;
|
|
ServiceDescriptorProtoFields[ServiceDescriptorProtoFields["method"] = 2] = "method";
|
|
// options = 3, // optional ServiceOptions options = 3;
|
|
})(ServiceDescriptorProtoFields || (ServiceDescriptorProtoFields = {}));
|