# # computing time of first use # Section 5.1, Figure 3 # Section 5.2, histograms in Figures 5-6 # # author: Robert Dyer <rdyer@bgsu.edu> # # Copyright 2013-2016 Iowa State University, Bowling Green State University. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY IOWA STATE UNIVERSITY ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL IOWA STATE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # The views and conclusions contained in the software and documentation are those # of the authors and should not be interpreted as representing official policies, # either expressed or implied, of Iowa State University. # ProjectUses: output sum[string][time] of int; FileUses: output sum[string][string][time] of int; Diamond: map[string] of time; BinaryLit: map[string] of time; Assert: map[string] of time; AnnotUse: map[string] of time; AnnotDefine: map[string] of time; Enums: map[string] of time; EnhancedFor: map[string] of time; GenDefField: map[string] of time; GenDefMethod: map[string] of time; GenDefType: map[string] of time; GenWildcard: map[string] of time; GenExtends: map[string] of time; GenSuper: map[string] of time; MultiCatch: map[string] of time; SafeVarargs: map[string] of time; TryResources: map[string] of time; UnderscoreLit: map[string] of time; Varargs: map[string] of time; RepeatedAnnot: map[string] of time; |
# # computing time of first use # Section 5.1, Figure 3 # Section 5.2, histograms in Figures 5-6 # # author: Robert Dyer <rdyer@bgsu.edu> # # Copyright 2013-2016 Iowa State University, Bowling Green State University. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY IOWA STATE UNIVERSITY ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL IOWA STATE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # The views and conclusions contained in the software and documentation are those # of the authors and should not be interpreted as representing official policies, # either expressed or implied, of Iowa State University. # ProjectUses: output sum[string][time] of int; FileUses: output sum[string][string][time] of int; Diamond: map[string] of time; BinaryLit: map[string] of time; Assert: map[string] of time; AnnotUse: map[string] of time; AnnotDefine: map[string] of time; Enums: map[string] of time; EnhancedFor: map[string] of time; GenDefField: map[string] of time; GenDefMethod: map[string] of time; GenDefType: map[string] of time; GenWildcard: map[string] of time; GenExtends: map[string] of time; GenSuper: map[string] of time; MultiCatch: map[string] of time; SafeVarargs: map[string] of time; TryResources: map[string] of time; UnderscoreLit: map[string] of time; Varargs: map[string] of time; RepeatedAnnot: map[string] of time; |
MethRefNew: map[string] of time; MethRefSuper: map[string] of time; MethRefExpr: map[string] of time; DefaultMeth: map[string] of time; |
|
RcvParam: map[string] of time; Diamond2: map[string] of ChangeKind; BinaryLit2: map[string] of ChangeKind; Assert2: map[string] of ChangeKind; AnnotUse2: map[string] of ChangeKind; AnnotDefine2: map[string] of ChangeKind; Enums2: map[string] of ChangeKind; EnhancedFor2: map[string] of ChangeKind; GenDefField2: map[string] of ChangeKind; GenDefMethod2: map[string] of ChangeKind; GenDefType2: map[string] of ChangeKind; GenWildcard2: map[string] of ChangeKind; GenExtends2: map[string] of ChangeKind; GenSuper2: map[string] of ChangeKind; MultiCatch2: map[string] of ChangeKind; SafeVarargs2: map[string] of ChangeKind; TryResources2: map[string] of ChangeKind; UnderscoreLit2: map[string] of ChangeKind; Varargs2: map[string] of ChangeKind; RepeatedAnnot2: map[string] of ChangeKind; |
RcvParam: map[string] of time; Diamond2: map[string] of ChangeKind; BinaryLit2: map[string] of ChangeKind; Assert2: map[string] of ChangeKind; AnnotUse2: map[string] of ChangeKind; AnnotDefine2: map[string] of ChangeKind; Enums2: map[string] of ChangeKind; EnhancedFor2: map[string] of ChangeKind; GenDefField2: map[string] of ChangeKind; GenDefMethod2: map[string] of ChangeKind; GenDefType2: map[string] of ChangeKind; GenWildcard2: map[string] of ChangeKind; GenExtends2: map[string] of ChangeKind; GenSuper2: map[string] of ChangeKind; MultiCatch2: map[string] of ChangeKind; SafeVarargs2: map[string] of ChangeKind; TryResources2: map[string] of ChangeKind; UnderscoreLit2: map[string] of ChangeKind; Varargs2: map[string] of ChangeKind; RepeatedAnnot2: map[string] of ChangeKind; |
MethRefNew2: map[string] of ChangeKind; MethRefSuper2: map[string] of ChangeKind; MethRefExpr2: map[string] of ChangeKind; DefaultMeth2: map[string] of ChangeKind; |
|
RcvParam2: map[string] of ChangeKind; record_feature_use := function(fileMap: map[string] of time, kinds: map[string] of ChangeKind, commit_date: time, f: ChangedFile) { if (haskey(fileMap, f.name)) return; fileMap[f.name] = commit_date; kinds[f.name] = f.change; }; cur_date: time; cur_file: ChangedFile; in_field: bool; visit(input, visitor { before node: ChangedFile -> { if (!iskind("SOURCE_JAVA_JLS", node.kind) || node.change == ChangeKind.DELETED) stop; cur_file = node; } before node: Revision -> if (int(node.commit_date) < 1) stop; else cur_date = node.commit_date; before node: Declaration -> { found1 := false; s1: set of string; foreach (i: int; node.modifiers[i]) if (contains(s1, node.modifiers[i].annotation_name)) found1 = true; else add(s1, node.modifiers[i].annotation_name); if (found1) record_feature_use(RepeatedAnnot, RepeatedAnnot2, cur_date, cur_file); if (node.kind == TypeKind.ANNOTATION) record_feature_use(AnnotDefine, AnnotDefine2, cur_date, cur_file); if (len(node.generic_parameters) > 0) record_feature_use(GenDefType, GenDefType2, cur_date, cur_file); if (node.kind == TypeKind.ENUM) record_feature_use(Enums, Enums2, cur_date, cur_file); in_field = true; foreach (i: int; def(node.fields[i])) visit(node.fields[i]); in_field = false; } before node: Type -> { if (strfind("?", node.name) > -1 && !match(`\?\s*super\s+.+`, node.name) && !match(`\?\s*extends\s+.+`, node.name)) record_feature_use(GenWildcard, GenWildcard2, cur_date, cur_file); if (match(`\?\s*extends\s+.+`, node.name)) record_feature_use(GenExtends, GenExtends2, cur_date, cur_file); if (match(`\?\s*super\s+.+`, node.name)) record_feature_use(GenSuper, GenSuper2, cur_date, cur_file); if (in_field && strfind("<", node.name) > -1) record_feature_use(GenDefField, GenDefField2, cur_date, cur_file); } before node: Method -> { found2 := false; s2: set of string; foreach (i: int; node.modifiers[i]) if (contains(s2, node.modifiers[i].annotation_name)) found2 = true; else add(s2, node.modifiers[i].annotation_name); if (found2) record_feature_use(RepeatedAnnot, RepeatedAnnot2, cur_date, cur_file); if (len(node.arguments) > 0 && node.arguments[0].variable_type.name == "this") record_feature_use(RcvParam, RcvParam2, cur_date, cur_file); if (len(node.generic_parameters) > 0) record_feature_use(GenDefMethod, GenDefMethod2, cur_date, cur_file); # @SafeVarargs if (has_annotation(node, "SafeVarargs")) { record_feature_use(SafeVarargs, SafeVarargs2, cur_date, cur_file); } else { # @SuppressWarnings({"unchecked", "varargs"}) mod := get_annotation(node, "SuppressWarnings"); if (def(mod)) foreach (i: int; mod.annotation_members[i] == "value") { e := mod.annotation_values[i]; if (e.kind == ExpressionKind.ARRAYINIT) { foundUnchecked := false; foundVarargs := false; foreach (j: int; e.expressions[j].kind == ExpressionKind.LITERAL) { if (e.expressions[j].literal == "unchecked") foundUnchecked = true; if (e.expressions[j].literal == "varargs") foundVarargs = true; } if (foundUnchecked && foundVarargs) record_feature_use(SafeVarargs, SafeVarargs2, cur_date, cur_file); } break; } } if (len(node.arguments) > 0 && strfind("...", node.arguments[len(node.arguments) - 1].variable_type.name) > -1) record_feature_use(Varargs, Varargs2, cur_date, cur_file); } before node: Variable -> { found3 := false; s3: set of string; foreach (i: int; node.modifiers[i]) if (contains(s3, node.modifiers[i].annotation_name)) found3 = true; else add(s3, node.modifiers[i].annotation_name); if (found3) record_feature_use(RepeatedAnnot, RepeatedAnnot2, cur_date, cur_file); } before node: Statement -> { switch (node.kind) { case StatementKind.ASSERT: record_feature_use(Assert, Assert2, cur_date, cur_file); break; case StatementKind.CATCH: if (strfind("|", node.variable_declaration.variable_type.name) > -1) record_feature_use(MultiCatch, MultiCatch2, cur_date, cur_file); break; case StatementKind.TRY: if (len(node.initializations) > 0) record_feature_use(TryResources, TryResources2, cur_date, cur_file); break; case StatementKind.FOR: if (def(node.variable_declaration)) record_feature_use(EnhancedFor, EnhancedFor2, cur_date, cur_file); break; default: break; } } before node: Expression -> |
RcvParam2: map[string] of ChangeKind; record_feature_use := function(fileMap: map[string] of time, kinds: map[string] of ChangeKind, commit_date: time, f: ChangedFile) { if (haskey(fileMap, f.name)) return; fileMap[f.name] = commit_date; kinds[f.name] = f.change; }; cur_date: time; cur_file: ChangedFile; in_field: bool; visit(input, visitor { before node: ChangedFile -> { if (!iskind("SOURCE_JAVA_JLS", node.kind) || node.change == ChangeKind.DELETED) stop; cur_file = node; } before node: Revision -> if (int(node.commit_date) < 1) stop; else cur_date = node.commit_date; before node: Declaration -> { found1 := false; s1: set of string; foreach (i: int; node.modifiers[i]) if (contains(s1, node.modifiers[i].annotation_name)) found1 = true; else add(s1, node.modifiers[i].annotation_name); if (found1) record_feature_use(RepeatedAnnot, RepeatedAnnot2, cur_date, cur_file); if (node.kind == TypeKind.ANNOTATION) record_feature_use(AnnotDefine, AnnotDefine2, cur_date, cur_file); if (len(node.generic_parameters) > 0) record_feature_use(GenDefType, GenDefType2, cur_date, cur_file); if (node.kind == TypeKind.ENUM) record_feature_use(Enums, Enums2, cur_date, cur_file); in_field = true; foreach (i: int; def(node.fields[i])) visit(node.fields[i]); in_field = false; } before node: Type -> { if (strfind("?", node.name) > -1 && !match(`\?\s*super\s+.+`, node.name) && !match(`\?\s*extends\s+.+`, node.name)) record_feature_use(GenWildcard, GenWildcard2, cur_date, cur_file); if (match(`\?\s*extends\s+.+`, node.name)) record_feature_use(GenExtends, GenExtends2, cur_date, cur_file); if (match(`\?\s*super\s+.+`, node.name)) record_feature_use(GenSuper, GenSuper2, cur_date, cur_file); if (in_field && strfind("<", node.name) > -1) record_feature_use(GenDefField, GenDefField2, cur_date, cur_file); } before node: Method -> { found2 := false; s2: set of string; foreach (i: int; node.modifiers[i]) if (contains(s2, node.modifiers[i].annotation_name)) found2 = true; else add(s2, node.modifiers[i].annotation_name); if (found2) record_feature_use(RepeatedAnnot, RepeatedAnnot2, cur_date, cur_file); if (len(node.arguments) > 0 && node.arguments[0].variable_type.name == "this") record_feature_use(RcvParam, RcvParam2, cur_date, cur_file); if (len(node.generic_parameters) > 0) record_feature_use(GenDefMethod, GenDefMethod2, cur_date, cur_file); # @SafeVarargs if (has_annotation(node, "SafeVarargs")) { record_feature_use(SafeVarargs, SafeVarargs2, cur_date, cur_file); } else { # @SuppressWarnings({"unchecked", "varargs"}) mod := get_annotation(node, "SuppressWarnings"); if (def(mod)) foreach (i: int; mod.annotation_members[i] == "value") { e := mod.annotation_values[i]; if (e.kind == ExpressionKind.ARRAYINIT) { foundUnchecked := false; foundVarargs := false; foreach (j: int; e.expressions[j].kind == ExpressionKind.LITERAL) { if (e.expressions[j].literal == "unchecked") foundUnchecked = true; if (e.expressions[j].literal == "varargs") foundVarargs = true; } if (foundUnchecked && foundVarargs) record_feature_use(SafeVarargs, SafeVarargs2, cur_date, cur_file); } break; } } if (len(node.arguments) > 0 && strfind("...", node.arguments[len(node.arguments) - 1].variable_type.name) > -1) record_feature_use(Varargs, Varargs2, cur_date, cur_file); } before node: Variable -> { found3 := false; s3: set of string; foreach (i: int; node.modifiers[i]) if (contains(s3, node.modifiers[i].annotation_name)) found3 = true; else add(s3, node.modifiers[i].annotation_name); if (found3) record_feature_use(RepeatedAnnot, RepeatedAnnot2, cur_date, cur_file); } before node: Statement -> { switch (node.kind) { case StatementKind.ASSERT: record_feature_use(Assert, Assert2, cur_date, cur_file); break; case StatementKind.CATCH: if (strfind("|", node.variable_declaration.variable_type.name) > -1) record_feature_use(MultiCatch, MultiCatch2, cur_date, cur_file); break; case StatementKind.TRY: if (len(node.initializations) > 0) record_feature_use(TryResources, TryResources2, cur_date, cur_file); break; case StatementKind.FOR: if (def(node.variable_declaration)) record_feature_use(EnhancedFor, EnhancedFor2, cur_date, cur_file); break; default: break; } } before node: Expression -> |
if (node.kind == ExpressionKind.METHOD_REFERENCE) { if (def(node.new_type)) record_feature_use(MethRefNew, MethRefNew2, cur_date, cur_file); else if (match(`super$`, node.literal)) record_feature_use(MethRefSuper, MethRefSuper2, cur_date, cur_file); else record_feature_use(MethRefExpr, MethRefExpr2, cur_date, cur_file); } else if (node.kind == ExpressionKind.LITERAL && def(node.literal)) { |
if (node.kind == ExpressionKind.LITERAL && def(node.literal)) { |
if (match(`^0[bB][01]([01_]*[01])?[Ll]?$`, node.literal)) record_feature_use(BinaryLit, BinaryLit2, cur_date, cur_file); if (strfind("_", node.literal) > -1 && match(`^(0[bBx])?([0-9]+.[0-9]+)?[0-9A-Fa-f]([0-9A-Fa-f_]*[0-9A-Fa-f])?[FfLl]?$`, node.literal)) record_feature_use(UnderscoreLit, UnderscoreLit2, cur_date, cur_file); } else if (node.kind == ExpressionKind.NEW && def(node.new_type) && strfind("<>", node.new_type.name) > -1) record_feature_use(Diamond, Diamond2, cur_date, cur_file); before node: Modifier -> if (node.kind == ModifierKind.ANNOTATION) record_feature_use(AnnotUse, AnnotUse2, cur_date, cur_file); |
if (match(`^0[bB][01]([01_]*[01])?[Ll]?$`, node.literal)) record_feature_use(BinaryLit, BinaryLit2, cur_date, cur_file); if (strfind("_", node.literal) > -1 && match(`^(0[bBx])?([0-9]+.[0-9]+)?[0-9A-Fa-f]([0-9A-Fa-f_]*[0-9A-Fa-f])?[FfLl]?$`, node.literal)) record_feature_use(UnderscoreLit, UnderscoreLit2, cur_date, cur_file); } else if (node.kind == ExpressionKind.NEW && def(node.new_type) && strfind("<>", node.new_type.name) > -1) record_feature_use(Diamond, Diamond2, cur_date, cur_file); before node: Modifier -> if (node.kind == ModifierKind.ANNOTATION) record_feature_use(AnnotUse, AnnotUse2, cur_date, cur_file); |
else if (node.other == "default") record_feature_use(DefaultMeth, DefaultMeth2, cur_date, cur_file); |
|
}); changekind_to_string := function(kind: ChangeKind) : string { if (kind == ChangeKind.ADDED) return "Add"; return "Change"; }; output_feature_first_use := function(name: string, fileMap: map[string] of time, kinds: map[string] of ChangeKind) { keyset := keys(fileMap); if (len(keyset) == 0) return; minval:time = now(); for (i := 0; i < len(keyset); i++) { minval = min(minval, fileMap[keyset[i]]); FileUses[name][changekind_to_string(kinds[keyset[0]])][fileMap[keyset[i]]] << 1; } ProjectUses[name][minval] << 1; }; output_feature_first_use("Diamond", Diamond, Diamond2); output_feature_first_use("BinaryLit", BinaryLit, BinaryLit2); output_feature_first_use("Assert", Assert, Assert2); output_feature_first_use("AnnotUse", AnnotUse, AnnotUse2); output_feature_first_use("AnnotDefine", AnnotDefine, AnnotDefine2); output_feature_first_use("Enums", Enums, Enums2); output_feature_first_use("EnhancedFor", EnhancedFor, EnhancedFor2); output_feature_first_use("GenDefField", GenDefField, GenDefField2); output_feature_first_use("GenDefMethod", GenDefMethod, GenDefMethod2); output_feature_first_use("GenDefType", GenDefType, GenDefType2); output_feature_first_use("GenWildcard", GenWildcard, GenWildcard2); output_feature_first_use("GenExtends", GenExtends, GenExtends2); output_feature_first_use("GenSuper", GenSuper, GenSuper2); output_feature_first_use("MultiCatch", MultiCatch, MultiCatch2); output_feature_first_use("SafeVarargs", SafeVarargs, SafeVarargs2); output_feature_first_use("TryResources", TryResources, TryResources2); output_feature_first_use("UnderscoreLit", UnderscoreLit, UnderscoreLit2); output_feature_first_use("Varargs", Varargs, Varargs2); output_feature_first_use("RepeatedAnnot", RepeatedAnnot, RepeatedAnnot2); output_feature_first_use("RcvParam", RcvParam, RcvParam2); |
}); changekind_to_string := function(kind: ChangeKind) : string { if (kind == ChangeKind.ADDED) return "Add"; return "Change"; }; output_feature_first_use := function(name: string, fileMap: map[string] of time, kinds: map[string] of ChangeKind) { keyset := keys(fileMap); if (len(keyset) == 0) return; minval:time = now(); for (i := 0; i < len(keyset); i++) { minval = min(minval, fileMap[keyset[i]]); FileUses[name][changekind_to_string(kinds[keyset[0]])][fileMap[keyset[i]]] << 1; } ProjectUses[name][minval] << 1; }; output_feature_first_use("Diamond", Diamond, Diamond2); output_feature_first_use("BinaryLit", BinaryLit, BinaryLit2); output_feature_first_use("Assert", Assert, Assert2); output_feature_first_use("AnnotUse", AnnotUse, AnnotUse2); output_feature_first_use("AnnotDefine", AnnotDefine, AnnotDefine2); output_feature_first_use("Enums", Enums, Enums2); output_feature_first_use("EnhancedFor", EnhancedFor, EnhancedFor2); output_feature_first_use("GenDefField", GenDefField, GenDefField2); output_feature_first_use("GenDefMethod", GenDefMethod, GenDefMethod2); output_feature_first_use("GenDefType", GenDefType, GenDefType2); output_feature_first_use("GenWildcard", GenWildcard, GenWildcard2); output_feature_first_use("GenExtends", GenExtends, GenExtends2); output_feature_first_use("GenSuper", GenSuper, GenSuper2); output_feature_first_use("MultiCatch", MultiCatch, MultiCatch2); output_feature_first_use("SafeVarargs", SafeVarargs, SafeVarargs2); output_feature_first_use("TryResources", TryResources, TryResources2); output_feature_first_use("UnderscoreLit", UnderscoreLit, UnderscoreLit2); output_feature_first_use("Varargs", Varargs, Varargs2); output_feature_first_use("RepeatedAnnot", RepeatedAnnot, RepeatedAnnot2); output_feature_first_use("RcvParam", RcvParam, RcvParam2); |
output_feature_first_use("DefaultMeth", DefaultMeth, DefaultMeth2); output_feature_first_use("MethRefNew", MethRefNew, MethRefNew2); output_feature_first_use("MethRefSuper", MethRefSuper, MethRefSuper2); output_feature_first_use("MethRefExpr", MethRefExpr, MethRefExpr2); |