Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript, hbs and Ruby syntax support #1

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
618c155
replaced esprima with babel parser
vivek-freshworks Mar 1, 2024
ac4065a
enabled cleanup for unsupported patterns
vivek-freshworks Mar 11, 2024
cb1333d
minor change
vivek-freshworks Mar 12, 2024
b29cd31
added support for template files
vivek-freshworks Mar 19, 2024
739e571
changes for init/constructor & computed cleanup
vivek-freshworks Mar 22, 2024
56f6210
reduceIfStatements for subexpression
vivek-freshworks Mar 26, 2024
57a0cc8
add support for ruby (#2)
Bennet-Sunder Mar 27, 2024
a72c322
Access related changes & dependency fixes
geophilusd Mar 29, 2024
a8c0356
minow fix for hbs
vivek-freshworks Apr 3, 2024
121b180
Merge branch 'fs-main' of https://github.com/freshworks/piranha into …
vivek-freshworks Apr 3, 2024
bc7492e
fix to template-refactor.js
vivek-freshworks Apr 8, 2024
e1fcb89
absolute path changes
vivek-freshworks Apr 21, 2024
d1bba65
conditional log
vivek-freshworks Apr 22, 2024
66834e2
Fs main (#5)
Bennet-Sunder May 2, 2024
2ed75aa
optimization
vivek-freshworks May 4, 2024
acbd36f
Merge branch 'uber:master' into fs-main
Bennet-Sunder May 15, 2024
a0e9f9c
updated release
Bennet-Sunder May 15, 2024
bf9996f
updated to limited release
Bennet-Sunder May 15, 2024
f15c7a2
Update polyglot_release.yml
Bennet-Sunder May 15, 2024
343ecc8
Update Cargo.toml
Bennet-Sunder May 15, 2024
f8a7393
Update polyglot_release.yml
Bennet-Sunder May 15, 2024
f458da4
Update polyglot_release.yml
Bennet-Sunder May 15, 2024
b76ac87
Update Cargo.toml
Bennet-Sunder May 15, 2024
2aade62
Update polyglot_release.yml
Bennet-Sunder May 15, 2024
7708749
more changes
Bennet-Sunder May 16, 2024
d43f392
more changes
Bennet-Sunder May 16, 2024
bc8b84f
more changes
Bennet-Sunder May 16, 2024
00c39f7
more changes
Bennet-Sunder May 16, 2024
0509dab
more changes
Bennet-Sunder May 17, 2024
1de82c2
parenthesis fixes
Bennet-Sunder May 19, 2024
bd0661f
merge fixes
Bennet-Sunder May 20, 2024
a5e2647
Merge remote-tracking branch 'uber-piranha/master' into fs-main
Bennet-Sunder May 21, 2024
1b6da2b
merge fixes
Bennet-Sunder May 21, 2024
77c7e54
changes for multi properties, need to do proper config
vivek-freshworks May 21, 2024
68ca7e9
remove blank lines
Bennet-Sunder May 27, 2024
cf23a1c
Merge pull request #6 from freshworks/remove_blank_lines
Bennet-Sunder May 27, 2024
c03d116
frontend config changes
vivek-freshworks May 28, 2024
b908d1a
Merge branch 'fs-main' of https://github.com/freshworks/piranha into …
vivek-freshworks May 28, 2024
5d5f040
revert few changes
vivek-freshworks May 28, 2024
66fe562
additional cleanup rules
Bennet-Sunder May 29, 2024
e1b7d90
Merge branch 'uber:master' into ruby_additional_rules
Bennet-Sunder May 29, 2024
60555b9
Merge branch 'uber:master' into fs-main
Bennet-Sunder May 29, 2024
273bc30
Merge pull request #7 from freshworks/ruby_additional_rules
Bennet-Sunder May 29, 2024
e096889
Merge branch 'uber:master' into fs-main
Bennet-Sunder Jun 2, 2024
6cb0572
Update polyglot_release.yml
Bennet-Sunder Jun 10, 2024
4d30bc9
Update polyglot_release.yml
Bennet-Sunder Jun 10, 2024
920a5fe
Merge branch 'uber:master' into fs-main
Bennet-Sunder Jun 10, 2024
458dc54
update version
Bennet-Sunder Jun 10, 2024
7e7b827
Revert "Update polyglot_release.yml"
Bennet-Sunder Jun 10, 2024
7d82c27
more rules
Bennet-Sunder Jun 10, 2024
fc98846
Merge pull request #8 from freshworks/more_ruby_rules
Bennet-Sunder Jun 10, 2024
5271e0b
updated version
Bennet-Sunder Jun 11, 2024
8795c7c
fixes for random comments removal
vivek-freshworks Jul 1, 2024
acafa1f
added rules for unless helper
vivek-freshworks Jul 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 11 additions & 55 deletions .github/workflows/polyglot_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ jobs:
pip install --upgrade maturin
maturin build --release -o dist
maturin build --sdist -o dist
- name: Pypi Release for ubuntu-latest
run: |
pip install twine
twine upload --skip-existing -u __token__ -p ${{ secrets.PYPI_TOKEN }} dist/*
- name: Archive production artifacts
uses: actions/upload-artifact@v2
with:
name: polyglot-piranha-package-ubuntu
path: dist/*
build_ubuntu_20:
runs-on: ubuntu-20.04
steps:
Expand All @@ -29,54 +30,9 @@ jobs:
run: |
pip install --upgrade maturin
maturin build --release -o dist
maturin build --sdist -o dist
- name: Pypi Release for ubuntu-latest
run: |
pip install twine
twine upload --skip-existing -u __token__ -p ${{ secrets.PYPI_TOKEN }} dist/*
macos_build_x86:
name: 'macos-x86'
runs-on: [macos-12]
strategy:
matrix:
arch: ['x86_64']
env:
# Polyglot depends on tree-sitter-python which tries to compile c++ files stdlibc++ which is depreciated in newer version of mac.
MACOSX_DEPLOYMENT_TARGET: 10.16
CXXFLAGS: -stdlib=libc++ -mmacosx-version-min=10.16
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Build wheel with Maturin
run: |
pip install --upgrade maturin
maturin build --release -o dist
- name: Pypi Release for macos-latest
run: |
pip install twine
twine upload --skip-existing -u __token__ -p ${{ secrets.PYPI_TOKEN }} dist/*
macos_build_arm:
name: 'macos-arm64'
runs-on: [macos-latest]
strategy:
matrix:
arch: ['arm64']
env:
# Polyglot depends on tree-sitter-python which tries to compile c++ files stdlibc++ which is depreciated in newer version of mac.
CXXFLAGS: -stdlib=libc++
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Build wheel with Maturin
run: |
rustup target add aarch64-apple-darwin
pip install --upgrade maturin
maturin build --release -o dist --target universal2-apple-darwin
- name: Pypi Release for macos-latest
run: |
pip install twine
twine upload --skip-existing -u __token__ -p ${{ secrets.PYPI_TOKEN }} dist/*
maturin build --sdist -o dist
- name: Archive production artifacts
uses: actions/upload-artifact@v2
with:
name: polyglot-piranha-package-ubuntu-20
path: dist/*
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = [
]
name = "piranha"
description = "Polyglot Piranha is a library for performing structural find and replace with deep cleanup."
version = "0.3.24"
version = "0.3.5"
edition = "2021"
include = ["pyproject.toml", "src/"]
exclude = ["legacy"]
Expand All @@ -34,7 +34,7 @@ doctest = false
cc = "1.0.73"

[dependencies]
tree-sitter = "0.20.6"
tree-sitter = "0.20.10"
tree-sitter-traversal = "0.1.2"
json = "0.12.4"
toml = "0.8.8"
Expand Down
18 changes: 18 additions & 0 deletions legacy/javascript/config/properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@
"methodName": "isToggleEnabled",
"flagType": "treated",
"argumentIndex": 0
},
{
"methodName": "hasTempFeature",
"flagType": "treated",
"argumentIndex": 0
},
{
"methodName": "ermFlagEnabled",
"flagType": "treated",
"argumentIndex": 0
}
],
"templateHelpers": [
{
"helperName": "has-temp-feature"
},
{
"helperName": "has-erm-flag"
}
]
}
111 changes: 111 additions & 0 deletions legacy/javascript/config/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
const babel = require("@babel/core");
const hasOwn = Object.prototype.hasOwnProperty;

const parseOptions = {
parser: {
parse: function (source, options) {
const babelOptions = getBabelOptions(options);
babelOptions.plugins.push("jsx", "flow", "decoratorAutoAccessors");
return adjustComments(require("@babel/parser").parse(source, babelOptions));
// return require("@babel/parser").parse(source, babelOptions);
}
}
}

function getOption(options, key, defaultValue) {
if (options && hasOwn.call(options, key)) {
return options[key];
}
return defaultValue;
}

function getBabelOptions(options) {
return {
sourceType: getOption(options, "sourceType", "module"),
strictMode: getOption(options, "strictMode", false),
allowImportExportEverywhere: true,
allowReturnOutsideFunction: true,
startLine: 1,
tokens: true,
plugins: [
"asyncGenerators",
"bigInt",
"classPrivateMethods",
"classPrivateProperties",
"classProperties",
"classStaticBlock",
"decimal",
"decorators-legacy",
"doExpressions",
"dynamicImport",
"exportDefaultFrom",
"exportExtensions",
"exportNamespaceFrom",
"functionBind",
"functionSent",
"importAssertions",
"importMeta",
"nullishCoalescingOperator",
"numericSeparator",
"objectRestSpread",
"optionalCatchBinding",
"optionalChaining",
[
"pipelineOperator",
{
proposal: "minimal",
},
],
[
"recordAndTuple",
{
syntaxType: "hash",
},
],
"throwExpressions",
"topLevelAwait",
"v8intrinsic",
],
};
}

function adjustComments(node) {
const seen = new WeakSet();

const copy = (from, to, leading, trailing) => {
from.forEach(comment => {
if (!seen.has(comment)) {
comment.leading = leading;
comment.trailing = trailing;
to.push(comment);
seen.add(comment);
}
})
}

babel.types.traverseFast(node, (node) => {
const comments = [];
if (node.leadingComments) {
copy(node.leadingComments, comments, true, false);
delete node.leadingComments;
}
if (node.innerComments) {
copy(node.innerComments, comments, false, false);
delete node.innerComments;
}
node.comments = comments;
});

babel.types.traverseFast(node, (node) => {
if (node.trailingComments) {
copy(node.trailingComments, node.comments, false, true);
delete node.trailingComments;
}
})

return node;
}

module.exports = {
parseOptions,
}
156 changes: 156 additions & 0 deletions legacy/javascript/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
const fs = require('fs');
const path = require('path');
const fg = require('fast-glob');
const recast = require("recast");
const ArgumentParser = require('argparse').ArgumentParser;
const jsRefactor = require("./src/refactor");
const { parseOptions } = require("./config/utils");
const templateRefactor = require("./src/template-refactor");
const templateRecast = require('ember-template-recast');

const parser = new ArgumentParser();
const requiredArgs = parser.addArgumentGroup();

requiredArgs.addArgument(['--flag'], {
help: 'Name of the stale flag',
required: true,
});

requiredArgs.addArgument(['--path'], {
help: 'Absolute directory path for flag cleanup',
require: true
});

requiredArgs.addArgument(['--output'], {
help: 'Absolute destination path of the refactored output files. File is modified in-place by default.'
});

requiredArgs.addArgument(['--properties'], {
help: 'Path of configuration file for Piranha',
required: true,
});

requiredArgs.addArgument(['--enable-log'], {
help: 'Print cleanup logs',
action: 'storeTrue',
defaultValue: false,
});

const args = parser.parseArgs();
let flagname = args.flag;

const propertiesInJson = fs.readFileSync(args.properties);
const properties = JSON.parse(propertiesInJson);
console.log(JSON.stringify(properties));

let jsFiles = [], templateFiles = [];
if(args.path.endsWith(".js")) {
jsFiles = [args.path];
} else if(args.path.endsWith(".hbs")) {
templateFiles = [args.path];
} else {
const excludeNodeModules = `!${path.join(args.path, 'node_modules/**')}`;
const excludeDist = `!${path.join(args.path, 'dist/**')}`;
jsFiles = fg.sync([
path.join(args.path, '**/*.js'), excludeNodeModules, excludeDist]
);
templateFiles = fg.sync([path.join(args.path, '**/*.hbs'), excludeNodeModules, excludeDist]);
}
console.log("Total JS files in frontend/app: ", jsFiles.length);
console.log("Total Templates files in frontend/app: ", templateFiles.length, "\n");

if(args.output) {
fs.rmdirSync(args.output, { recursive: true })
}

const filesHavingFlagKeyword = [], allModifiedFiles = [], templateToCleanupInfoMap = {};

//cleanup js files
for (let filename of jsFiles) {
const content = fs.readFileSync(filename, 'utf-8');
if(!content.includes(flagname)) continue;
const ast = recast.parse(content, parseOptions);

const engine = new jsRefactor.RefactorEngine(
ast,
properties,
true,
flagname,
15,
args.enable_log,
false,
filename,
);
const { changed, hasFlagKeywordInFile, templateCleanupInfo } = engine.refactorPipeline();
if (path.parse(filename).base === 'component.js') {
const templatePath = path.join(filename, "..", "template.hbs");
templateToCleanupInfoMap[templatePath] = templateCleanupInfo;
}

if (hasFlagKeywordInFile) filesHavingFlagKeyword.push(filename);
if (changed) {
allModifiedFiles.push(filename);
} else {
continue;
}

const output = recast.print(ast).code;
writeOutput(filename, output);
}

//cleanup templates
for (let filename of templateFiles) {
const content = fs.readFileSync(filename, 'utf8');

const cleanupInfo = templateToCleanupInfoMap[filename] || { properties: [] };
let hasFlagOrProperty = content.includes(flagname) || cleanupInfo.properties.some((prop) => content.includes(prop));
if(!hasFlagOrProperty) continue;

const ast = templateRecast.parse(content);

const engine = new templateRefactor.TemplateRefactorEngine({
ast,
properties,
flagname,
filename,
cleanupInfo,
print_to_console: args.enable_log,
});

const { changed, hasFlagKeywordInFile } = engine.refactorPipeline();

if (hasFlagKeywordInFile) filesHavingFlagKeyword.push(filename);
if (changed) {
allModifiedFiles.push(filename);
} else {
continue;
}

const output = templateRecast.print(ast);
writeOutput(filename, output);
}

function writeOutput(filename, output) {
const { base, dir } = path.parse(filename);
let outputDir = args.output ? path.join(args.output, dir) : dir;
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputpath = path.join(outputDir, base);
fs.writeFileSync(outputpath, output, function (err) {
if (err) {
return console.log(err);
}
console.log(`Output written to ${outputpath}`);
});
}

const diff1 = filesHavingFlagKeyword.filter(filename => !allModifiedFiles.includes(filename));
const diff2 = allModifiedFiles.filter(filename => !filesHavingFlagKeyword.includes(filename));
if (diff1.length) {
console.log("Attention: These files might need modification, please check them manually", diff1);
}
if (diff2.length) {
console.log("Attention: These files might not need modification, please check them manually", diff2);
}
console.log(`Total ${allModifiedFiles.length} files are modified by tool cleanup`)
Loading