-
Notifications
You must be signed in to change notification settings - Fork 7
/
content.js
151 lines (132 loc) · 5.45 KB
/
content.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Listen for messages */
var REGEX_IMPORT = /^(import )/;
var REGEX_PACKAGE_NAME_EXCLUDING_CLASS_NAME = /(.*\.)/;
var REGEX_BASE_PACKAGE;
// This will help us determine the line from which the actual code begins.
var INDEX_OF_LAST_IMPORT_STATEMENT = -1;
var arrayOfBroweseableClasses = [];
var PROTOCOL;
var DOMAIN;
var USER_NAME;
var REPOSITORY_NAME;
var BRANCH;
var MODULE_NAME; // gadle based projects have modules
var SOURCE_FOLDER_ROOT;
var ANDROID_REFERENCE_URL_BASE = "https://developer.android.com/reference/";
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
/* If the received message has the expected format... */
if (msg.task && (msg.task === "activate_class_links")) {
PROTOCOL = msg.protocol;
DOMAIN = msg.domain;
USER_NAME = msg.userName;
REPOSITORY_NAME = msg.repositoryName;
BRANCH = msg.branchName;
MODULE_NAME = msg.modulename;
SOURCE_FOLDER_ROOT = msg.sourceCodeFolder;
var packageNameFolders = msg.packageName.split(".");
REGEX_BASE_PACKAGE = new RegExp('(' + packageNameFolders[0] + '\.' + packageNameFolders[1] + ')');
var tableRows = $('div.blob-wrapper tr');
$(tableRows).each(function (index) {
var sourceCodeLine = $(this).find(':nth-child(2)').text();
if (itIsAnImportStatement(sourceCodeLine)) {
var packageName = getPackageName(sourceCodeLine);
if (packageBelongsToOurSourceCode(packageName) || packageBelongsToAndroid(packageName)) {
var className = getClassName(packageName);
if (className !== 'R') {
var browseableClass = new BrowseableClass(className, packageName);
arrayOfBroweseableClasses.push(browseableClass);
// console.log(browseableClass.getGithubUrl());
}
}
if (INDEX_OF_LAST_IMPORT_STATEMENT < index) {
INDEX_OF_LAST_IMPORT_STATEMENT = index;
}
}
});
chrome.storage.local.get({
newTab: true
}, function (r) {
var target = "";
if (r.newTab) {
target = "_blank";
}
for (var i = 0; i < arrayOfBroweseableClasses.length; i++) {
var el = $('td :contains(' + arrayOfBroweseableClasses[i].className + ')');
for (var j = 0; j < el.length; j++) {
var code = $(el[j]).text();
var result = code.match(REGEX_VALID_USAGE_OF_CLASS_NAME);
if (result) {
if (~code.indexOf('List') || ~code.indexOf('ArrayList') || ~code.indexOf('Set') || ~code.indexOf('Iterator')) {
// Handle more collections stuff probably wrapped inside a fucking function.
$(el[j]).wrapInner('<a href=\"' + arrayOfBroweseableClasses[i].getLinkedUrl() + '\" target=\"' + target + '\" />');
} else if (code.length === arrayOfBroweseableClasses[i].className.length) {
$(el[j]).wrapInner('<a href=\"' + arrayOfBroweseableClasses[i].getLinkedUrl() + '\" target=\"' + target + '\" />');
}
}
}
}
});
}
});
/**
* Checks if this line of code is an import statement.
* @param {String} lineOfCode
* @return (Boolean) true if it is an import statement and false otherwise
*/
function itIsAnImportStatement(lineOfCode) {
var result = lineOfCode.match(REGEX_IMPORT);
return !!result;
}
/**
* Checks if this package lies in our source code or not, by checking the first
* two folder names in the package. Like if com.ishankhanna.example.app is the
* is a package to be tested if it belongs to us or not, we will check if
* com.ishankhanna.example is there in this package name or not.
* @param {String} packageNameToBeValidated
* @returns {Boolean} true if it belongs to our source code and false otherwise
*/
function packageBelongsToOurSourceCode(packageNameToBeValidated) {
return !!packageNameToBeValidated.match(REGEX_BASE_PACKAGE);
}
/**
* Checks if the package belongs to android - simply checks if it starts with "android.*"
*/
function packageBelongsToAndroid(packageNameToBeValidated) {
return packageNameToBeValidated.startsWith("android.");
}
/**
* Extracts the package name from the import statement of the source code.
* @param {String} importStatement
* @return {String} packageName
*/
function getPackageName(importStatement) {
// TODO : Figure out why the hell are we doing this split twice.
var codes = importStatement.split(" ");
return codes[1].split(";")[0];
}
/**
* Extracts the class name from the package name.
* @param {String} packageName
* @return {String} className
*/
function getClassName(packageName) {
var elementsOfPackageName = packageName.split(".");
return elementsOfPackageName[elementsOfPackageName.length - 1];
}
function BrowseableClass(className, packageName) {
this.className = className;
this.packageName = packageName;
}
BrowseableClass.prototype.getLinkedUrl = function () {
if (packageBelongsToAndroid(this.packageName)) {
var packageNameWithSlashes = this.packageName.replace(/\./g, "\/");
return ANDROID_REFERENCE_URL_BASE + packageNameWithSlashes + ".html";
} else if (packageBelongsToOurSourceCode(this.packageName)) {
var result = this.packageName.match(REGEX_PACKAGE_NAME_EXCLUDING_CLASS_NAME);
var packageNameWithSlashes = result[0].replace(/\./g, "\/");
return PROTOCOL + "://" + DOMAIN + "/" + USER_NAME + "/" + REPOSITORY_NAME +
"/blob/" + BRANCH + "/" + MODULE_NAME + "/" + SOURCE_FOLDER_ROOT + "/"
+ packageNameWithSlashes + this.className + '.java';
}
};
var REGEX_VALID_USAGE_OF_CLASS_NAME = /^(\s+)?[A-Z][\S]+(\(|\.|>|\s|$)/;