mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 20:58:38 +02:00
Update JSBaker.cpp
This commit is contained in:
parent
9e91ab7630
commit
b86dd9dea4
1 changed files with 69 additions and 120 deletions
|
@ -9,11 +9,13 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <PathUtils.h> // To generate Temporary directory
|
#include <PathUtils.h>
|
||||||
|
|
||||||
#include "JSBaker.h"
|
#include "JSBaker.h"
|
||||||
#include "Baker.h"
|
#include "Baker.h"
|
||||||
|
|
||||||
|
const int ASCII_CHARACTERS_UPPER_LIMIT = 126;
|
||||||
|
|
||||||
JSBaker::JSBaker(const QUrl& jsURL, const QString& bakedOutputDir) :
|
JSBaker::JSBaker(const QUrl& jsURL, const QString& bakedOutputDir) :
|
||||||
_jsURL(jsURL),
|
_jsURL(jsURL),
|
||||||
_bakedOutputDir(bakedOutputDir)
|
_bakedOutputDir(bakedOutputDir)
|
||||||
|
@ -22,58 +24,22 @@ JSBaker::JSBaker(const QUrl& jsURL, const QString& bakedOutputDir) :
|
||||||
};
|
};
|
||||||
|
|
||||||
void JSBaker::bake() {
|
void JSBaker::bake() {
|
||||||
auto tempDir = PathUtils::generateTemporaryDir();
|
qCDebug(js_baking) << "JS Baker " << _jsURL << "bake starting";
|
||||||
|
|
||||||
if (tempDir.isEmpty()) {
|
// Import the script to start baking
|
||||||
handleError("Failed to create a temporary directory.");
|
importJS();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tempDir = tempDir;
|
|
||||||
|
|
||||||
_originalJSFilePath = _tempDir.filePath(_jsURL.fileName());
|
|
||||||
qCDebug(js_baking) << "Made temporary dir " << _tempDir;
|
|
||||||
qCDebug(js_baking) << "Origin file path: " << _originalJSFilePath;
|
|
||||||
|
|
||||||
// When source JS is loaded, trigger the importJS method
|
|
||||||
connect(this, &JSBaker::sourceJSLoaded, this, &JSBaker::importJS);
|
|
||||||
|
|
||||||
// Make a local copy of the JS File
|
|
||||||
loadSourceJS();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSBaker::loadSourceJS() {
|
|
||||||
// load the local file
|
|
||||||
QFile localJS{ _jsURL.toLocalFile() };
|
|
||||||
|
|
||||||
if (!localJS.exists()) {
|
|
||||||
|
|
||||||
handleError("Could not find " + _jsURL.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a copy of local file at _originalJSFilePath
|
|
||||||
qCDebug(js_baking) << "Local file url: " << _jsURL << _jsURL.toString() << _jsURL.toLocalFile() << ", copying to: " << _originalJSFilePath;
|
|
||||||
localJS.copy(_originalJSFilePath);
|
|
||||||
|
|
||||||
// emit signal to indicate script is ready to import
|
|
||||||
emit sourceJSLoaded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSBaker::importJS() {
|
void JSBaker::importJS() {
|
||||||
// Import the file to be processed from _originalJSFilePath
|
// Import the file to be processed from _jsURL
|
||||||
QFile jsFile(_originalJSFilePath);
|
QFile jsFile(_jsURL.toLocalFile());
|
||||||
if (!jsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!jsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
handleError("Error opening " + _originalJSFilePath + " for reading");
|
handleError("Error opening " + _originalJSFilePath + " for reading");
|
||||||
}
|
|
||||||
|
|
||||||
if (hasErrors()) {
|
|
||||||
// Return if cannot open file
|
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
// Import successful, Call the baking function with the imported file
|
|
||||||
bakeJS(&jsFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Import successful, Call the baking function with the imported file
|
||||||
|
bakeJS(&jsFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSBaker::bakeJS(QFile* inputFile) {
|
void JSBaker::bakeJS(QFile* inputFile) {
|
||||||
|
@ -82,8 +48,8 @@ void JSBaker::bakeJS(QFile* inputFile) {
|
||||||
outputFile.open(QIODevice::WriteOnly | QIODevice::Text);
|
outputFile.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
|
|
||||||
// Read from inputFile and write to outputFile per character
|
// Read from inputFile and write to outputFile per character
|
||||||
QTextStream readCharacter(inputFile);
|
QTextStream in(inputFile);
|
||||||
QTextStream writeCharacter(&outputFile);
|
QTextStream out(&outputFile);
|
||||||
|
|
||||||
// Algorithm requires the knowledge of previous and next character for each character read
|
// Algorithm requires the knowledge of previous and next character for each character read
|
||||||
QChar currentCharacter;
|
QChar currentCharacter;
|
||||||
|
@ -91,35 +57,33 @@ void JSBaker::bakeJS(QFile* inputFile) {
|
||||||
// Initialize previousCharacter with new line
|
// Initialize previousCharacter with new line
|
||||||
QChar previousCharacter = '\n';
|
QChar previousCharacter = '\n';
|
||||||
|
|
||||||
// Input currentCharacter
|
in >> currentCharacter;
|
||||||
readCharacter >> currentCharacter;
|
|
||||||
|
|
||||||
while (!readCharacter.atEnd()) {
|
while (!in.atEnd()) {
|
||||||
// input nextCharacter
|
in >> nextCharacter;
|
||||||
readCharacter >> nextCharacter;
|
|
||||||
|
|
||||||
if (currentCharacter == '\r') {
|
if (currentCharacter == '\r') {
|
||||||
writeCharacter << '\n';
|
out << '\n';
|
||||||
} else if (currentCharacter == '/') {
|
} else if (currentCharacter == '/') {
|
||||||
// Check if single line comment i.e. //
|
// Check if single line comment i.e. //
|
||||||
if (nextCharacter == '/') {
|
if (nextCharacter == '/') {
|
||||||
handleSingleLineComments(&readCharacter);
|
handleSingleLineComments(&in);
|
||||||
|
|
||||||
//Start fresh after handling comments
|
//Start fresh after handling comments
|
||||||
previousCharacter = '\n';
|
previousCharacter = '\n';
|
||||||
readCharacter >> currentCharacter;
|
in >> currentCharacter;
|
||||||
continue;
|
continue;
|
||||||
} else if (nextCharacter == '*') {
|
} else if (nextCharacter == '*') {
|
||||||
// Check if multi line comment i.e. /*
|
// Check if multi line comment i.e. /*
|
||||||
handleMultiLineComments(&readCharacter);
|
handleMultiLineComments(&in);
|
||||||
|
|
||||||
//Start fresh after handling comments
|
//Start fresh after handling comments
|
||||||
previousCharacter = '\n';
|
previousCharacter = '\n';
|
||||||
readCharacter >> currentCharacter;
|
in >> currentCharacter;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// If '/' is not followed by '/' or '*' print '/'
|
// If '/' is not followed by '/' or '*' print '/'
|
||||||
writeCharacter << currentCharacter;
|
out << currentCharacter;
|
||||||
}
|
}
|
||||||
} else if (isControlCharacter(currentCharacter)) {
|
} else if (isControlCharacter(currentCharacter)) {
|
||||||
// Check if white space or tab
|
// Check if white space or tab
|
||||||
|
@ -127,7 +91,7 @@ void JSBaker::bakeJS(QFile* inputFile) {
|
||||||
// Skip multiple spaces or tabs
|
// Skip multiple spaces or tabs
|
||||||
if (isControlCharacter(nextCharacter)) {
|
if (isControlCharacter(nextCharacter)) {
|
||||||
while (isControlCharacter(nextCharacter)) {
|
while (isControlCharacter(nextCharacter)) {
|
||||||
readCharacter >> nextCharacter;
|
in >> nextCharacter;
|
||||||
if (nextCharacter == '\n') {
|
if (nextCharacter == '\n') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -136,43 +100,42 @@ void JSBaker::bakeJS(QFile* inputFile) {
|
||||||
|
|
||||||
// check if space can be omitted
|
// check if space can be omitted
|
||||||
if (!canOmitSpace(previousCharacter, nextCharacter)) {
|
if (!canOmitSpace(previousCharacter, nextCharacter)) {
|
||||||
writeCharacter << ' ';
|
out << ' ';
|
||||||
}
|
}
|
||||||
} else if (currentCharacter == '\n') {
|
} else if (currentCharacter == '\n') {
|
||||||
// Check if new line
|
// Check if new line
|
||||||
|
|
||||||
//Skip multiple new lines
|
//Skip multiple new lines
|
||||||
//Skip new line followed by space or tab
|
//Skip new line followed by space or tab
|
||||||
if (nextCharacter == '\n' || isControlCharacter(nextCharacter)) {
|
while (nextCharacter == '\n' || isControlCharacter(nextCharacter)) {
|
||||||
while (nextCharacter == '\n' || isControlCharacter(nextCharacter)) {
|
in >> nextCharacter;
|
||||||
readCharacter >> nextCharacter;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if new line can be omitted
|
// Check if new line can be omitted
|
||||||
if (!canOmitNewLine(previousCharacter, nextCharacter)) {
|
if (!canOmitNewLine(previousCharacter, nextCharacter)) {
|
||||||
writeCharacter << '\n';
|
out << '\n';
|
||||||
}
|
}
|
||||||
} else if (isQuote(currentCharacter)) {
|
} else if (isQuote(currentCharacter)) {
|
||||||
// Print the current quote and nextCharacter as is
|
// Print the current quote and nextCharacter as is
|
||||||
writeCharacter << currentCharacter;
|
out << currentCharacter;
|
||||||
writeCharacter << nextCharacter;
|
out << nextCharacter;
|
||||||
|
|
||||||
// Store the type of quote we are processing
|
// Store the type of quote we are processing
|
||||||
QChar quote = currentCharacter;
|
QChar quote = currentCharacter;
|
||||||
|
|
||||||
// Don't modify the quoted strings
|
// Don't modify the quoted strings
|
||||||
while (nextCharacter != quote) {
|
while (nextCharacter != quote) {
|
||||||
readCharacter >> nextCharacter;
|
in >> nextCharacter;
|
||||||
writeCharacter << nextCharacter;
|
out << nextCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start fresh after handling quoted strings
|
//Start fresh after handling quoted strings
|
||||||
previousCharacter = nextCharacter;
|
previousCharacter = nextCharacter;
|
||||||
readCharacter >> currentCharacter;
|
in >> currentCharacter;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// In all other cases write the currentCharacter to outputFile
|
// In all other cases write the currentCharacter to outputFile
|
||||||
writeCharacter << currentCharacter;
|
out << currentCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
previousCharacter = currentCharacter;
|
previousCharacter = currentCharacter;
|
||||||
|
@ -181,7 +144,7 @@ void JSBaker::bakeJS(QFile* inputFile) {
|
||||||
|
|
||||||
//write currentCharacter to output file when nextCharacter reaches EOF
|
//write currentCharacter to output file when nextCharacter reaches EOF
|
||||||
if (currentCharacter != '\n') {
|
if (currentCharacter != '\n') {
|
||||||
writeCharacter << currentCharacter;
|
out << currentCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reading done. Closing the inputFile
|
// Reading done. Closing the inputFile
|
||||||
|
@ -207,38 +170,36 @@ void JSBaker::exportJS(QFile* bakedFile) {
|
||||||
|
|
||||||
if (!bakedFile->open(QIODevice::WriteOnly)) {
|
if (!bakedFile->open(QIODevice::WriteOnly)) {
|
||||||
handleError("Error opening " + _bakedJSFilePath + " for writing");
|
handleError("Error opening " + _bakedJSFilePath + " for writing");
|
||||||
}
|
|
||||||
|
|
||||||
if (hasErrors()) {
|
|
||||||
// cannot open bakedFile return
|
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
_outputFiles.push_back(_bakedJSFilePath);
|
|
||||||
qCDebug(js_baking) << "Exported" << _jsURL << "with re-written paths to" << _bakedJSFilePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export successful
|
||||||
|
_outputFiles.push_back(_bakedJSFilePath);
|
||||||
|
qCDebug(js_baking) << "Exported" << _jsURL << "with re-written paths to" << _bakedJSFilePath;
|
||||||
|
|
||||||
// Exporting done. Closing the outputFile
|
// Exporting done. Closing the outputFile
|
||||||
bakedFile->close();
|
bakedFile->close();
|
||||||
|
|
||||||
// emit signal to indicate the JS baking is finished
|
// emit signal to indicate the JS baking is finished
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSBaker::handleSingleLineComments(QTextStream * readCharacter) {
|
void JSBaker::handleSingleLineComments(QTextStream * in) {
|
||||||
QChar character;
|
QChar character;
|
||||||
while (!readCharacter->atEnd()) {
|
while (!in->atEnd()) {
|
||||||
*readCharacter >> character;
|
*in >> character;
|
||||||
if (character == '\n')
|
if (character == '\n') {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSBaker::handleMultiLineComments(QTextStream * readCharacter) {
|
void JSBaker::handleMultiLineComments(QTextStream * in) {
|
||||||
QChar character;
|
QChar character;
|
||||||
while (!readCharacter->atEnd()) {
|
while (!in->atEnd()) {
|
||||||
*readCharacter >> character;
|
*in >> character;
|
||||||
if (character == '*') {
|
if (character == '*') {
|
||||||
if (readCharacter->read(1) == '/') {
|
if (in->read(1) == '/') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,58 +208,46 @@ void JSBaker::handleMultiLineComments(QTextStream * readCharacter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JSBaker::canOmitSpace(QChar previousCharacter, QChar nextCharacter) {
|
bool JSBaker::canOmitSpace(QChar previousCharacter, QChar nextCharacter) {
|
||||||
if ((isAlphanum(previousCharacter) || isNonAscii(previousCharacter) || isSpecialCharacter(previousCharacter)) &&
|
return(!((isAlphanum(previousCharacter) || isNonAscii(previousCharacter) || isSpecialCharacter(previousCharacter)) &&
|
||||||
(isAlphanum(nextCharacter) || isNonAscii(nextCharacter) || isSpecialCharacter(nextCharacter))
|
(isAlphanum(nextCharacter) || isNonAscii(nextCharacter) || isSpecialCharacter(nextCharacter)))
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JSBaker::canOmitNewLine(QChar previousCharacter, QChar nextCharacter) {
|
bool JSBaker::canOmitNewLine(QChar previousCharacter, QChar nextCharacter) {
|
||||||
if ((isAlphanum(previousCharacter) || isNonAscii(previousCharacter) || isSpecialCharacterPrevious(previousCharacter)) &&
|
return (!((isAlphanum(previousCharacter) || isNonAscii(previousCharacter) || isSpecialCharacterPrevious(previousCharacter)) &&
|
||||||
(isAlphanum(nextCharacter) || isNonAscii(nextCharacter) || isSpecialCharacterNext(nextCharacter))
|
(isAlphanum(nextCharacter) || isNonAscii(nextCharacter) || isSpecialCharacterNext(nextCharacter)))
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if character is alphabet, number or one of the following: '_', '$', '\\'
|
//Check if character is alphabet, number or one of the following: '_', '$', '\\' or a non-ASCII character
|
||||||
bool JSBaker::isAlphanum(QChar c) {
|
bool JSBaker::isAlphanum(QChar c) {
|
||||||
return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
|
return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
|
||||||
|| c == '_' || c == '$' || c == '\\' || c > 126);
|
|| c == '_' || c == '$' || c == '\\' || c > ASCII_CHARACTERS_UPPER_LIMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JSBaker::isNonAscii(QChar c) {
|
bool JSBaker::isNonAscii(QChar c) {
|
||||||
return ((int)c.toLatin1() > 127);
|
return ((int)c.toLatin1() > ASCII_CHARACTERS_UPPER_LIMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If previous and next characters are special characters, don't omit space
|
||||||
bool JSBaker::isSpecialCharacter(QChar c) {
|
bool JSBaker::isSpecialCharacter(QChar c) {
|
||||||
if (c == '\'' || c == '$' || c == '_' || c == '/') {
|
return (c == '\'' || c == '$' || c == '_' || c == '/');
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If previous character is a special character, maybe don't omit new line (depends on next character as well)
|
||||||
bool JSBaker::isSpecialCharacterPrevious(QChar c) {
|
bool JSBaker::isSpecialCharacterPrevious(QChar c) {
|
||||||
if (c == '\'' || c == '$' || c == '_' || c == '}' || c == ']' || c == ')' || c == '+' || c == '-'
|
return (c == '\'' || c == '$' || c == '_' || c == '}' || c == ']' || c == ')' || c == '+' || c == '-'
|
||||||
|| c == '"' || c == "'") {
|
|| c == '"' || c == "'");
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If next character is a special character, maybe don't omit new line (depends on previous character as well)
|
||||||
bool JSBaker::isSpecialCharacterNext(QChar c) {
|
bool JSBaker::isSpecialCharacterNext(QChar c) {
|
||||||
if (c == '\'' || c == '$' || c == '_' || c == '{' || c == '[' || c == '(' || c == '+' || c == '-') {
|
return (c == '\'' || c == '$' || c == '_' || c == '{' || c == '[' || c == '(' || c == '+' || c == '-');
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if white space or tab
|
// Check if white space or tab
|
||||||
bool JSBaker::isControlCharacter(QChar c) {
|
bool JSBaker::isControlCharacter(QChar c) {
|
||||||
return (c == ' ' || (int)c.toLatin1() == 9);
|
return (c == ' ' || c == '\t');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check If the currentCharacter is " or ' or `
|
// Check If the currentCharacter is " or ' or `
|
||||||
|
|
Loading…
Reference in a new issue