-
Notifications
You must be signed in to change notification settings - Fork 0
/
fileprocessor.js
159 lines (145 loc) · 5.67 KB
/
fileprocessor.js
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2024 Joseph P Medley
'use strict';
const utils = require('./utils.js');
const { IDLError } = require('./errors.js');
const {
CallbackData,
DictionaryData,
EnumData,
IncludesData,
InterfaceData
} = require('./interfacedata.js');
const CALLBACK_RE = /callback\s*(\w*)\s*=[^;]*;/;
const CALLBACK_CANDIDATE_RE = /callback[\w\s]*=/;
const DICTIONARY_RE = /\s*dictionary\s*(\w*)[^{]*\{[^}]*\};/m;
const ENUM_RE = /\b\s*enum\s*(\w*)[^{]*\{[^}]*\};/gm;
const ENUM_CANDIDATE_RE = /\b\s*enum\b/;
const INCLUDES_RE = /^\s?(\w*)\s*includes\s*(\w*)\s*;/gm;
const INTERFACE_RE = /(\[.*\])?.*(interface)[^\{]*\{.*(?<=});/s;
const INTERFACE_CANDIDATE_RE = /(callback|partial)?\s*(?<!")interface\s*(mixin)?[^\{]*/m;
const INTERFACE_HEADER_RE = INTERFACE_CANDIDATE_RE;
const METAFILE = Object.freeze({
flag: null,
path: '',
key: '',
keys: null,
originTrial: null,
tree: null,
type: ''
});
const STARTS = ["[", "callback", "dictionary", "enum", "interface", "partial", "typedef"];
const IDL_OBJECTS = Object.freeze({
"[": InterfaceData,
"callback": CallbackData,
"dictionary": DictionaryData,
"enum": EnumData,
"includes": IncludesData,
"interface": InterfaceData,
"mixin": InterfaceData,
"partial": InterfaceData
});
class FileProcesser {
constructor(sourcePath) {
this._sourcePath = sourcePath;
this._sourceContents = utils.getIDLFile(this._sourcePath, { clean: true });
}
// Gets new options argument with interfaces only default
process(resultCallback) {
const processOptions = {
"sourcePath": this._sourcePath,
"flag": false,
"originTrial": false
};
this._processInterface(resultCallback, processOptions);
this._processCallback(resultCallback, processOptions);
this._processDictionary(resultCallback, processOptions);
this._processEnum(resultCallback, processOptions);
this._processIncludes(resultCallback, processOptions);
}
_processInterface(resultCallback, options) {
let interfaceCandidate = this._sourceContents.match(INTERFACE_CANDIDATE_RE);
if (!interfaceCandidate) { return; }
let foundInterface = this._sourceContents.match(INTERFACE_RE);
if (!foundInterface) {
const msg = `File ${this._sourcePath} contains malformed interface.`;
throw new IDLError(msg, this._sourcePath);
}
let interfaceHeader = this._sourceContents.match(INTERFACE_HEADER_RE);
let interfaceMeta;
if (interfaceHeader[1] === 'callback') {
// Callback inerfaces (as opposed to callback functions) are treated the
// same as standard interfaces.
interfaceMeta = new IDL_OBJECTS['interface'](foundInterface[0], options);
} else if (interfaceHeader[1] === 'partial') {
interfaceMeta = new IDL_OBJECTS['partial'](foundInterface[0], options);
} else if (interfaceHeader[2] === 'mixin') {
options.type = 'mixin';
interfaceMeta = new IDL_OBJECTS['mixin'](foundInterface[0], options);
} else {
interfaceMeta = new IDL_OBJECTS['interface'](foundInterface[0], options);
}
options.flag = interfaceMeta.flagged;
options.originTrial = interfaceMeta.originTrial;
options.realSource = foundInterface[0];
resultCallback(interfaceMeta);
}
_processCallback(resultCallback, options) {
let callbackCandidate = this._sourceContents.match(CALLBACK_CANDIDATE_RE);
if (!callbackCandidate) { return; }
let foundCallback = this._sourceContents.match(CALLBACK_RE);
if (!foundCallback) {
if (this._sourceContents.includes('callback interface')) { return; }
const msg = `File ${this._sourcePath} contains a malformed callback.`;
throw new IDLError(msg, this._sourcePath);
}
const callbackMeta = new IDL_OBJECTS['callback'](foundCallback[0], options);
callbackMeta.flag = options.flag;
callbackMeta.originTrial = options.originTrial;
resultCallback(callbackMeta);
}
_processDictionary(resultCallback, options) {
if (this._sourceContents.includes('dictionary')) {
let foundDictionary = this._sourceContents.match(DICTIONARY_RE);
if (!foundDictionary) {
const msg = `File ${this._sourcePath} contains a malformed dictionary.`;
throw new IDLError(msg, this._sourcePath);
}
const dictionaryMeta = new IDL_OBJECTS['dictionary'](foundDictionary[0], options);
dictionaryMeta.flag = options.flag;
dictionaryMeta.originTrial = options.originTrial;
resultCallback(dictionaryMeta);
}
}
_processEnum(resultCallback, options) {
let enumCandidate = this._sourceContents.match(ENUM_CANDIDATE_RE);
if (!enumCandidate) { return; }
let foundEnum = this._sourceContents.match(ENUM_RE);
if (!foundEnum) {
const msg = `File ${this._sourcePath} contains a malformed enum.`;
throw new IDLError(msg, this._sourcePath);
}
const enumMeta = new IDL_OBJECTS['enum'](foundEnum[0], options);
enumMeta.flag = options.flag;
enumMeta.originTrial = options.originTrial;
resultCallback(enumMeta);
}
_processIncludes(resultCallback, options) {
if (this._sourceContents.includes('includes')) {
let foundIncludes = this._sourceContents.matchAll(INCLUDES_RE);
if (!foundIncludes) {
const msg = `File ${this._sourcePath} contains a malformed includes statement.`;
throw new IDLError(msg, this._sourcePath);
}
for ( const fi of foundIncludes) {
const includesMeta = new IDL_OBJECTS['includes'](fi[0], options);
includesMeta.flagged = options.flag;
includesMeta.originTrial = options.originTrial;
resultCallback(includesMeta);
}
return foundIncludes;
}
}
}
module.exports.FileProcessor = FileProcesser;
module.exports.IDLError = IDLError;
module.exports.METAFILE = METAFILE;