You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
9.7 KiB
306 lines
9.7 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.addObjcImports = addObjcImports;
|
|
exports.findObjcFunctionCodeBlock = findObjcFunctionCodeBlock;
|
|
exports.findObjcInterfaceCodeBlock = findObjcInterfaceCodeBlock;
|
|
exports.findSwiftFunctionCodeBlock = findSwiftFunctionCodeBlock;
|
|
exports.insertContentsInsideObjcFunctionBlock = insertContentsInsideObjcFunctionBlock;
|
|
exports.insertContentsInsideObjcInterfaceBlock = insertContentsInsideObjcInterfaceBlock;
|
|
exports.insertContentsInsideSwiftClassBlock = insertContentsInsideSwiftClassBlock;
|
|
exports.insertContentsInsideSwiftFunctionBlock = insertContentsInsideSwiftFunctionBlock;
|
|
|
|
function _commonCodeMod() {
|
|
const data = require("../utils/commonCodeMod");
|
|
|
|
_commonCodeMod = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _matchBrackets() {
|
|
const data = require("../utils/matchBrackets");
|
|
|
|
_matchBrackets = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Add Objective-C import
|
|
* @param source source contents
|
|
* @param imports array of imports, e.g. ['<Foundation/Foundation.h>']
|
|
* @returns updated contents
|
|
*/
|
|
function addObjcImports(source, imports) {
|
|
const lines = source.split('\n'); // Try to insert statements after first #import where would probably not in #if block
|
|
|
|
const lineIndexWithFirstImport = lines.findIndex(line => line.match(/^#import .*$/));
|
|
|
|
for (const importElement of imports) {
|
|
if (!source.includes(importElement)) {
|
|
const importStatement = `#import ${importElement}`;
|
|
lines.splice(lineIndexWithFirstImport + 1, 0, importStatement);
|
|
}
|
|
}
|
|
|
|
return lines.join('\n');
|
|
}
|
|
/**
|
|
* Find code block of Objective-C interface or implementation
|
|
*
|
|
* @param contents source contents
|
|
* @param declaration interface/implementation, e.g. '@interface Foo'
|
|
* @returns found CodeBlock, or null if not found
|
|
*/
|
|
|
|
|
|
function findObjcInterfaceCodeBlock(contents, declaration) {
|
|
const start = contents.search(new RegExp(`^${declaration}\\W`, 'm'));
|
|
|
|
if (start < 0) {
|
|
return null;
|
|
}
|
|
|
|
let end = contents.indexOf('\n@end', start);
|
|
end += 5; // '\n@end'.length === 5
|
|
|
|
return {
|
|
start,
|
|
end,
|
|
code: contents.substring(start, end)
|
|
};
|
|
}
|
|
/**
|
|
* Find code block of Objective-C function without declaration, will return only {} block
|
|
*
|
|
* @param contents source contents
|
|
* @param selector function selector, e.g. 'doSomething:withSomeValue:'
|
|
* @returns found CodeBlock, or null if not found.
|
|
*/
|
|
|
|
|
|
function findObjcFunctionCodeBlock(contents, selector) {
|
|
const symbols = selector.split(':');
|
|
const argsCount = symbols.length - 1;
|
|
let pattern = '^[\\-+]\\s*\\(.+?\\)';
|
|
|
|
if (argsCount === 0) {
|
|
pattern += `${symbols[0]}\\s+`;
|
|
} else {
|
|
for (let i = 0; i < argsCount; ++i) {
|
|
const argSymbol = `${symbols[i]}:\\(.+\\)\\w+`;
|
|
pattern += `${argSymbol}\\s+`;
|
|
}
|
|
}
|
|
|
|
pattern += '{';
|
|
let start = contents.search(new RegExp(pattern, 'm'));
|
|
|
|
if (start < 0) {
|
|
return null;
|
|
}
|
|
|
|
start = contents.indexOf('{', start);
|
|
const end = (0, _matchBrackets().findMatchingBracketPosition)(contents, '{', start);
|
|
return {
|
|
start,
|
|
end,
|
|
code: contents.substring(start, end + 1)
|
|
};
|
|
}
|
|
/**
|
|
* Insert contents to the Objective-C function block
|
|
*
|
|
* @param srcContents source contents
|
|
* @param selector function selector, e.g. 'doSomething:withSomeValue:'
|
|
* @param insertion code to insert
|
|
* @param options insertion options
|
|
* @returns updated contents
|
|
*/
|
|
|
|
|
|
function insertContentsInsideObjcFunctionBlock(srcContents, selector, insertion, options) {
|
|
return insertContentsInsideFunctionBlock(srcContents, selector, insertion, options, 'objc');
|
|
}
|
|
/**
|
|
* Insert contents to the Objective-C interface/implementation block
|
|
*
|
|
* @param srcContents source contents
|
|
* @param declaration interface/implementation, e.g. '@interface Foo'
|
|
* @param insertion code to insert
|
|
* @param options insertion options
|
|
* @returns updated contents
|
|
*/
|
|
|
|
|
|
function insertContentsInsideObjcInterfaceBlock(srcContents, declaration, insertion, options) {
|
|
const codeBlock = findObjcInterfaceCodeBlock(srcContents, declaration);
|
|
|
|
if (!codeBlock) {
|
|
return srcContents;
|
|
}
|
|
|
|
const {
|
|
position
|
|
} = options;
|
|
|
|
if (position === 'head') {
|
|
const firstNewLineIndex = srcContents.indexOf('\n', codeBlock.start);
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, insertion, firstNewLineIndex);
|
|
} else if (position === 'tail') {
|
|
const endLen = '@end'.length;
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, insertion, codeBlock.end - endLen);
|
|
}
|
|
|
|
return srcContents;
|
|
}
|
|
/**
|
|
* Find code block of Swift function without declaration, will return only {} block
|
|
*
|
|
* @param contents source contents
|
|
* @param selector function selector, e.g. 'doSomething(_:withSomeValue:)'
|
|
* @returns found CodeBlock, or null if not found.
|
|
*/
|
|
|
|
|
|
function findSwiftFunctionCodeBlock(contents, selector) {
|
|
const parenthesesIndex = selector.indexOf('('); // `functName` === 'doSomething' of 'doSomething(_:withSomeValue:)'
|
|
|
|
const funcName = selector.substring(0, parenthesesIndex); // `argLabels` === ['_', 'withSomeValue'] 'doSomething(_:withSomeValue:)'
|
|
|
|
const argLabels = selector.substring(parenthesesIndex + 1, selector.length - 2).split(':');
|
|
let searchOffset = 0;
|
|
const funcCandidateRegExp = new RegExp(`\\sfunc\\s+${funcName}\\(`, 'm');
|
|
let funcCandidateOffset = (0, _commonCodeMod().searchFromOffset)(contents, funcCandidateRegExp, searchOffset);
|
|
|
|
while (funcCandidateOffset >= 0) {
|
|
// Parse function parameters
|
|
const paramsStartOffset = contents.indexOf('(', funcCandidateOffset);
|
|
const paramsEndOffset = (0, _matchBrackets().findMatchingBracketPosition)(contents, '(', paramsStartOffset);
|
|
const paramsString = contents.substring(paramsStartOffset + 1, paramsEndOffset);
|
|
const params = paramsString.split(',').map(parseSwiftFunctionParam); // Prepare offset for next round
|
|
|
|
searchOffset = paramsEndOffset + 1;
|
|
funcCandidateOffset = (0, _commonCodeMod().searchFromOffset)(contents, funcCandidateRegExp, searchOffset); // Try to match function parameters
|
|
|
|
if (argLabels.length !== params.length) {
|
|
continue;
|
|
}
|
|
|
|
for (let i = 0; i < argLabels.length; ++i) {
|
|
if (argLabels[i] !== params[i].argumentLabel) {
|
|
continue;
|
|
}
|
|
} // This function is matched one, get the code block.
|
|
|
|
|
|
const codeBlockStart = contents.indexOf('{', paramsEndOffset);
|
|
const codeBlockEnd = (0, _matchBrackets().findMatchingBracketPosition)(contents, '{', paramsEndOffset);
|
|
const codeBlock = contents.substring(codeBlockStart, codeBlockEnd + 1);
|
|
return {
|
|
start: codeBlockStart,
|
|
end: codeBlockEnd,
|
|
code: codeBlock
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function parseSwiftFunctionParam(paramTuple) {
|
|
const semiIndex = paramTuple.indexOf(':');
|
|
const [argumentLabel, parameterName] = paramTuple.substring(0, semiIndex).split(/\s+/);
|
|
const typeString = paramTuple.substring(semiIndex + 1).trim();
|
|
return {
|
|
argumentLabel,
|
|
parameterName,
|
|
typeString
|
|
};
|
|
}
|
|
/**
|
|
* Insert contents to the swift class block
|
|
*
|
|
* @param srcContents source contents
|
|
* @param declaration class/extension declaration, e.g. 'class AppDelegate'
|
|
* @param insertion code to append
|
|
* @param options insertion options
|
|
* @returns updated contents
|
|
*/
|
|
|
|
|
|
function insertContentsInsideSwiftClassBlock(srcContents, declaration, insertion, options) {
|
|
const start = srcContents.search(new RegExp(`\\s*${declaration}.*?[\\(\\{]`));
|
|
|
|
if (start < 0) {
|
|
throw new Error(`Unable to find class code block - declaration[${declaration}]`);
|
|
}
|
|
|
|
const {
|
|
position
|
|
} = options;
|
|
|
|
if (position === 'head') {
|
|
const firstBracketIndex = srcContents.indexOf('{', start);
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, insertion, firstBracketIndex + 1);
|
|
} else if (position === 'tail') {
|
|
const endBracketIndex = (0, _matchBrackets().findMatchingBracketPosition)(srcContents, '{', start);
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, insertion, endBracketIndex);
|
|
}
|
|
|
|
return srcContents;
|
|
}
|
|
/**
|
|
* Insert contents to the Swift function block
|
|
*
|
|
* @param srcContents source contents
|
|
* @param selector function selector, e.g. 'doSomething:withSomeValue:'
|
|
* @param insertion code to insert
|
|
* @param options insertion options
|
|
* @returns updated contents
|
|
*/
|
|
|
|
|
|
function insertContentsInsideSwiftFunctionBlock(srcContents, selector, insertion, options) {
|
|
return insertContentsInsideFunctionBlock(srcContents, selector, insertion, options, 'swift');
|
|
}
|
|
|
|
function insertContentsInsideFunctionBlock(srcContents, selector, insertion, options, language) {
|
|
var _options$indent;
|
|
|
|
const codeBlock = language === 'objc' ? findObjcFunctionCodeBlock(srcContents, selector) : findSwiftFunctionCodeBlock(srcContents, selector);
|
|
|
|
if (!codeBlock) {
|
|
return srcContents;
|
|
}
|
|
|
|
const {
|
|
position
|
|
} = options;
|
|
const indent = ' '.repeat((_options$indent = options.indent) !== null && _options$indent !== void 0 ? _options$indent : 2);
|
|
|
|
if (position === 'head') {
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, `\n${indent}${insertion}`, codeBlock.start + 1);
|
|
} else if (position === 'tail') {
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, `\n${indent}${insertion}`, codeBlock.end - 1);
|
|
} else if (position === 'tailBeforeLastReturn') {
|
|
let lastReturnIndex = srcContents.lastIndexOf(' return ', codeBlock.end);
|
|
|
|
if (lastReturnIndex < 0) {
|
|
throw new Error(`Cannot find last return statement:\n${srcContents}`);
|
|
}
|
|
|
|
lastReturnIndex += 1; // +1 for the prefix space
|
|
|
|
srcContents = (0, _commonCodeMod().insertContentsAtOffset)(srcContents, `${insertion}\n${indent}`, lastReturnIndex);
|
|
}
|
|
|
|
return srcContents;
|
|
}
|
|
//# sourceMappingURL=codeMod.js.map
|