work on module ignoring

This commit is contained in:
John Bintz 2008-10-08 21:20:30 -04:00
parent a059b00bac
commit 09215aaeea
7 changed files with 128 additions and 41 deletions

20
README
View File

@ -15,6 +15,26 @@ To build & use Harmonious Code on Unix-like operating systems:
* Run build/command_line.sh and pass the path to a PHP file as the first * Run build/command_line.sh and pass the path to a PHP file as the first
parameter. A basic analysis should appear. parameter. A basic analysis should appear.
To automatically ignore certain tokens and modules, place lines like
the following in your code:
* To globally ignore a token (ex: json_decode()), place at the top of
the file the following:
//harmonious json_decode
* To ignore a token within a block of code, surround the code in the
following:
//harmonious json_decode
...your code...
//harmonious_end
* To ignore a particular module throughout the code (ex: maxdb), place
at the top of the file the following:
//harmonious @maxdb
No build instructions for Windows yet, but Cygwin + haXe for Windows should No build instructions for Windows yet, but Cygwin + haXe for Windows should
be able to perform the build. be able to perform the build.

View File

@ -1,8 +1,10 @@
class CodeParser { class CodeParser {
public var tokenProcessors(getTokenProcessors, null) : Hash<TokenProcessor>; public var token_processors(get_token_processors, null) : Hash<TokenProcessor>;
public var ignored_modules(get_ignored_modules, null) : Hash<Bool>;
public function new() { public function new() {
this.tokenProcessors = new Hash<TokenProcessor>(); this.token_processors = new Hash<TokenProcessor>();
this.ignored_modules = new Hash<Bool>();
} }
#if neko #if neko
@ -13,7 +15,7 @@ class CodeParser {
functionProcessor.save_to_cache(); functionProcessor.save_to_cache();
} }
this.tokenProcessors.set(Type.getClassName(Type.getClass(functionProcessor)), functionProcessor); this.token_processors.set(Type.getClassName(Type.getClass(functionProcessor)), functionProcessor);
} }
#end #end
@ -21,10 +23,11 @@ class CodeParser {
var functionProcessor = new FunctionTokenProcessor(); var functionProcessor = new FunctionTokenProcessor();
functionProcessor.load_from_resource(); functionProcessor.load_from_resource();
this.tokenProcessors.set(Type.getClassName(Type.getClass(functionProcessor)), functionProcessor); this.token_processors.set(Type.getClassName(Type.getClass(functionProcessor)), functionProcessor);
} }
public function getTokenProcessors() { return this.tokenProcessors; } public function get_token_processors() { return this.token_processors; }
public function get_ignored_modules() { return this.ignored_modules; }
private function flatten_tokens_to_ignore(tokens_to_ignore : Array<Hash<Bool>>) : Hash<Bool> { private function flatten_tokens_to_ignore(tokens_to_ignore : Array<Hash<Bool>>) : Hash<Bool> {
var flattened_tokens = new Hash<Bool>(); var flattened_tokens = new Hash<Bool>();
@ -38,8 +41,9 @@ class CodeParser {
public function parse(s : String) : Array<Result> { public function parse(s : String) : Array<Result> {
var results = new Array<Result>(); var results = new Array<Result>();
this.ignored_modules = new Hash<Bool>();
var function_token_processor = this.tokenProcessors.get("FunctionTokenProcessor"); var function_token_processor = this.token_processors.get("FunctionTokenProcessor");
var function_tokens_found = new Hash<Bool>(); var function_tokens_found = new Hash<Bool>();
var tokens_to_ignore = new Array<Hash<Bool>>(); var tokens_to_ignore = new Array<Hash<Bool>>();
@ -120,8 +124,14 @@ class CodeParser {
new_tokens_to_ignore.shift(); new_tokens_to_ignore.shift();
var tokens_to_ignore_hash = new Hash<Bool>(); var tokens_to_ignore_hash = new Hash<Bool>();
for (token in new_tokens_to_ignore) { for (token in new_tokens_to_ignore) {
if (token.charAt(0) == "@") {
if (token.toLowerCase() != "@php") {
this.ignored_modules.set(token.substr(1), true);
}
} else {
tokens_to_ignore_hash.set(token, true); tokens_to_ignore_hash.set(token, true);
} }
}
tokens_to_ignore.push(tokens_to_ignore_hash); tokens_to_ignore.push(tokens_to_ignore_hash);
} }
flattened_tokens = flatten_tokens_to_ignore(tokens_to_ignore); flattened_tokens = flatten_tokens_to_ignore(tokens_to_ignore);

View File

@ -106,27 +106,24 @@ class CodeVersionInformation {
var version_lists = new Hash<Array<String>>(); var version_lists = new Hash<Array<String>>();
var version_match = ~/^([^\ ]+) (.*)$/; var version_match = ~/^([^\ ]+) (.*)$/;
for (part in s.split(", ")) { for (part in s.split(", ")) {
if (version_match.match(part)) { var parts = breakdown_php_version_string(part);
var source = version_match.matched(1); var source = parts[0];
if (!version_lists.exists(source)) { if (!version_lists.exists(source)) {
version_lists.set(source, new Array<String>()); version_lists.set(source, new Array<String>());
} }
var tmp = version_lists.get(source); var tmp = version_lists.get(source);
tmp.push(version_match.matched(2)); tmp.push(parts[1]);
version_lists.set(source, tmp); version_lists.set(source, tmp);
} }
}
var final_versions = new Hash<String>(); var final_versions = new Hash<String>();
for (source in version_lists.keys()) { for (source in version_lists.keys()) {
var tmp = version_lists.get(source); final_versions.set(source, CodeVersionInformation.get_lowest_version(version_lists.get(source)));
tmp.sort(CodeVersionInformation.version_compare);
final_versions.set(source, tmp.join(", "));
} }
return final_versions; return final_versions;
} }
public function new(results : Array<Result>) { public function new(results : Array<Result>, ?ignored_modules : Hash<Bool>) {
var start_minimum_versions = new Hash<Array<String>>(); var start_minimum_versions = new Hash<Array<String>>();
var start_maximum_versions = new Hash<Array<String>>(); var start_maximum_versions = new Hash<Array<String>>();
@ -140,6 +137,12 @@ class CodeVersionInformation {
if (version_string_info.length > 0) { if (version_string_info.length > 0) {
var source = version_string_info[0]; var source = version_string_info[0];
var ok_to_use = true;
if (ignored_modules != null) {
ok_to_use = !ignored_modules.exists(source);
}
if (ok_to_use) {
if (!internal_minimum_version.exists(source)) { if (!internal_minimum_version.exists(source)) {
internal_minimum_version.set(source, new Array<String>()); internal_minimum_version.set(source, new Array<String>());
} }
@ -159,6 +162,7 @@ class CodeVersionInformation {
} }
} }
} }
}
merge_versions(start_minimum_versions, internal_minimum_version, true); merge_versions(start_minimum_versions, internal_minimum_version, true);
merge_versions(start_maximum_versions, internal_maximum_version, false); merge_versions(start_maximum_versions, internal_maximum_version, false);

View File

@ -2,6 +2,7 @@ class JavaScriptTarget {
static public var code_parser : CodeParser; static public var code_parser : CodeParser;
static public var current_results : Array<Result>; static public var current_results : Array<Result>;
static public var show_only_modules : Hash<Bool>; static public var show_only_modules : Hash<Bool>;
static public var ignored_modules : Hash<Bool>;
static public function main() { static public function main() {
var function_token = new FunctionToken("a","a"); var function_token = new FunctionToken("a","a");
@ -10,6 +11,7 @@ class JavaScriptTarget {
code_parser.loadProcessorsFromResources(); code_parser.loadProcessorsFromResources();
show_only_modules = new Hash<Bool>(); show_only_modules = new Hash<Bool>();
ignored_modules = new Hash<Bool>();
#if js #if js
var loading_div = js.Lib.document.getElementById("loading"); var loading_div = js.Lib.document.getElementById("loading");
@ -22,6 +24,7 @@ class JavaScriptTarget {
static public function get_results(s : String) { static public function get_results(s : String) {
current_results = code_parser.parse(s); current_results = code_parser.parse(s);
ignored_modules = code_parser.ignored_modules;
} }
static public function change_result(index_id : Int, state : Bool) : Bool { static public function change_result(index_id : Int, state : Bool) : Bool {
@ -39,6 +42,17 @@ class JavaScriptTarget {
show_only_modules.set(module, !show_only_modules.get(module)); show_only_modules.set(module, !show_only_modules.get(module));
} }
static public function change_module_ignore(module : String, state : Bool) {
ignored_modules.set(module, state);
}
static public function toggle_ignore_module(module: String) {
if (!ignored_modules.exists(module)) {
ignored_modules.set(module, false);
}
ignored_modules.set(module, !ignored_modules.get(module));
}
#if js #if js
static public function change_result_and_redraw(result_checkbox : Dynamic) { static public function change_result_and_redraw(result_checkbox : Dynamic) {
var index_id_search = ~/^result-enabled-([0-9]+)$/; var index_id_search = ~/^result-enabled-([0-9]+)$/;
@ -51,12 +65,16 @@ class JavaScriptTarget {
} }
static public function display_version_information() { static public function display_version_information() {
var version_info = new CodeVersionInformation(current_results); var version_info = new CodeVersionInformation(current_results, ignored_modules);
var output = "Your code in requires the following minimum PHP & PECL module versions:<ul>"; var output = "Your code in requires the following minimum PHP & PECL module versions:";
var minimum = version_info.final_versions.get("minimum"); var minimum = version_info.final_versions.get("minimum");
output += "<form action=\"\" onsubmit=\"return false\">";
output += "<ul>";
for (module in minimum.keys()) { for (module in minimum.keys()) {
output += "<li>" + module + ": " + minimum.get(module) + "</li>"; output += "<li>" + module + ": " + minimum.get(module) + "</li>";
} }
@ -80,8 +98,6 @@ class JavaScriptTarget {
output += "<p><strong>This code may not run!</strong></p>"; output += "<p><strong>This code may not run!</strong></p>";
} }
output += "<form action=\"\" onsubmit=\"return false\">";
output += "<table cellspacing=\"0\" id=\"results-list\">"; output += "<table cellspacing=\"0\" id=\"results-list\">";
output += "<tr><th>Token</th><th>Ignore?</th>"; output += "<tr><th>Token</th><th>Ignore?</th>";
@ -104,6 +120,7 @@ class JavaScriptTarget {
for (result in current_results) { for (result in current_results) {
var ok_to_show = true; var ok_to_show = true;
var modules_check_out = true; var modules_check_out = true;
var any_visible_modules = false;
if (!result.is_enabled) { ignored_tokens.push(result.token); } if (!result.is_enabled) { ignored_tokens.push(result.token); }
@ -116,7 +133,16 @@ class JavaScriptTarget {
} }
} }
for (module in max_versions.keys()) {
if (ignored_modules.exists(module)) {
if (!ignored_modules.get(module)) { any_visible_modules = true; }
} else {
any_visible_modules = true;
}
}
if (modules_check_out) { ok_to_show = true; } if (modules_check_out) { ok_to_show = true; }
if (!any_visible_modules) { ok_to_show = false; }
if (ok_to_show) { if (ok_to_show) {
var result_class = (result.is_enabled ? "enabled" : "disabled"); var result_class = (result.is_enabled ? "enabled" : "disabled");
@ -174,5 +200,10 @@ class JavaScriptTarget {
JavaScriptTarget.toggle_module(module); JavaScriptTarget.toggle_module(module);
JavaScriptTarget.display_version_information(); JavaScriptTarget.display_version_information();
} }
static public function toggle_ignore_module_and_redraw(module : String) {
JavaScriptTarget.toggle_ignore_module(module);
JavaScriptTarget.display_version_information();
}
#end #end
} }

View File

@ -5,14 +5,16 @@ class TestCodeParser extends haxe.unit.TestCase {
[ "this is my array_shift() json_encode() cpdf_arc()", "3", "{minimum => {PHP => 5.2.0, json => 1.2.0}, maximum => {PHP => 5.0.5}}" ], [ "this is my array_shift() json_encode() cpdf_arc()", "3", "{minimum => {PHP => 5.2.0, json => 1.2.0}, maximum => {PHP => 5.0.5}}" ],
[ "array_shift()", "1", "{minimum => {PHP => 4}, maximum => {}}" ], [ "array_shift()", "1", "{minimum => {PHP => 4}, maximum => {}}" ],
[ "//harmonious json_encode\narray_shift() json_encode()\n//harmonious_end", "1", "{minimum => {PHP => 4}, maximum => {}}" ], [ "//harmonious json_encode\narray_shift() json_encode()\n//harmonious_end", "1", "{minimum => {PHP => 4}, maximum => {}}" ],
[ "//harmonious json_encode\narray_shift() json_encode()\n//harmonious_end\njson_encode()", "2", "{minimum => {PHP => 5.2.0, json => 1.2.0}, maximum => {}}" ] [ "//harmonious json_encode\narray_shift() json_encode()\n//harmonious_end\njson_encode()", "2", "{minimum => {PHP => 5.2.0, json => 1.2.0}, maximum => {}}" ],
[ "//harmonious @json\narray_shift() json_encode()\n//harmonious_end\njson_encode()", "2", "{minimum => {PHP => 5.2.0}, maximum => {}}" ],
[ "//harmonious @PHP\narray_shift()", "1", "{minimum => {PHP => 4}, maximum => {}}" ]
]; ];
#if neko #if neko
function testCodeParserLoadTokens() { function testCodeParserLoadTokens() {
var p = new CodeParser(); var p = new CodeParser();
p.loadProcessorsFromDisk(); p.loadProcessorsFromDisk();
assertTrue(p.tokenProcessors.exists("FunctionTokenProcessor")); assertTrue(p.token_processors.exists("FunctionTokenProcessor"));
} }
function testProcessCode() { function testProcessCode() {
@ -21,8 +23,9 @@ class TestCodeParser extends haxe.unit.TestCase {
for (code in test_code) { for (code in test_code) {
var result = p.parse(code[0]); var result = p.parse(code[0]);
var ignored_modules = p.ignored_modules;
assertEquals(Std.parseInt(code[1]), result.length); assertEquals(Std.parseInt(code[1]), result.length);
var code_version_info = new CodeVersionInformation(result); var code_version_info = new CodeVersionInformation(result, ignored_modules);
assertEquals(code[2], code_version_info.final_versions.toString()); assertEquals(code[2], code_version_info.final_versions.toString());
} }
} }

View File

@ -70,8 +70,8 @@ class TestCodeVersionInformation extends haxe.unit.TestCase {
function testGetVersionStringSplit() { function testGetVersionStringSplit() {
assertEquals("{xmlwriter => 2.0.4, PHP => 4}", CodeVersionInformation.split_version_string("PHP 4, xmlwriter 2.0.4").toString()); assertEquals("{xmlwriter => 2.0.4, PHP => 4}", CodeVersionInformation.split_version_string("PHP 4, xmlwriter 2.0.4").toString());
assertEquals("{xmlwriter => 2.0.4, PHP => 4 &gt;= 4.0.3}", CodeVersionInformation.split_version_string("PHP 4 &gt;= 4.0.3, xmlwriter 2.0.4").toString()); assertEquals("{xmlwriter => 2.0.4, PHP => 4.0.3}", CodeVersionInformation.split_version_string("PHP 4 &gt;= 4.0.3, xmlwriter 2.0.4").toString());
assertEquals("{PHP => 4, 5}", CodeVersionInformation.split_version_string("PHP 5, PHP 4").toString()); assertEquals("{PHP => 4}", CodeVersionInformation.split_version_string("PHP 5, PHP 4").toString());
} }
function testGetModuleInformation() { function testGetModuleInformation() {
@ -83,4 +83,17 @@ class TestCodeVersionInformation extends haxe.unit.TestCase {
assertEquals("[PHP, xmod, zmod]", v.all_modules.toString()); assertEquals("[PHP, xmod, zmod]", v.all_modules.toString());
} }
function testIgnoreModules() {
var valid_results = [
new Result(ResultType.Function, "one", "PHP 4, zmod 5"),
new Result(ResultType.Function, "two", "PHP 4 &gt;= 4.0.6, xmod 5"),
new Result(ResultType.Function, "three", "zmod 5"),
];
var ignored_modules = new Hash<Bool>();
ignored_modules.set("xmod", true);
var v = new CodeVersionInformation(valid_results, ignored_modules);
assertEquals("[PHP, zmod]", v.all_modules.toString());
}
} }

View File

@ -14,5 +14,11 @@ class TestJavaScriptTarget extends haxe.unit.TestCase {
assertEquals("{}", JavaScriptTarget.show_only_modules.toString()); assertEquals("{}", JavaScriptTarget.show_only_modules.toString());
JavaScriptTarget.toggle_module("zip"); JavaScriptTarget.toggle_module("zip");
assertEquals("{zip => true}", JavaScriptTarget.show_only_modules.toString()); assertEquals("{zip => true}", JavaScriptTarget.show_only_modules.toString());
assertEquals("{}", JavaScriptTarget.ignored_modules.toString());
JavaScriptTarget.change_module_ignore("zip", true);
assertEquals("{zip => true}", JavaScriptTarget.ignored_modules.toString());
JavaScriptTarget.change_module_ignore("zip", false);
assertEquals("{zip => false}", JavaScriptTarget.ignored_modules.toString());
} }
} }