author | Joe Walker <jwalker@mozilla.com> |
Fri, 24 Aug 2012 11:05:07 +0100 | |
changeset 103439 | 7bf846af58d35674c1b02f8dbfa260f6012a78d5 |
parent 103438 | 6b00d1edb2e717b0d658dc3408fae6f38add9b02 |
child 103440 | 35e5ee61e193771a906a39c7d21e66651cf03ae0 |
push id | 13991 |
push user | ryanvm@gmail.com |
push date | Sun, 26 Aug 2012 02:29:03 +0000 |
treeherder | mozilla-inbound@c4f20a024113 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | harth |
bugs | 775031 |
milestone | 17.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/devtools/commandline/gcli.jsm +++ b/browser/devtools/commandline/gcli.jsm @@ -2334,16 +2334,17 @@ function Command(commandSpec) { if (this.params == null) { this.params = []; } if (!Array.isArray(this.params)) { throw new Error('command.params must be an array in ' + this.name); } + this.hasNamedParameters = false; this.description = 'description' in this ? this.description : undefined; this.description = lookup(this.description, 'canonDescNone'); this.manual = 'manual' in this ? this.manual : undefined; this.manual = lookup(this.manual); // At this point this.params has nested param groups. We want to flatten it // out and replace the param object literals with Parameter objects var paramSpecs = this.params; @@ -2368,22 +2369,30 @@ function Command(commandSpec) { if (!spec.group) { if (usingGroups) { console.error('Parameters can\'t come after param groups.' + ' Ignoring ' + this.name + '/' + spec.name); } else { var param = new Parameter(spec, this, null); this.params.push(param); + + if (!param.isPositionalAllowed) { + this.hasNamedParameters = true; + } } } else { spec.params.forEach(function(ispec) { var param = new Parameter(ispec, this, spec.group); this.params.push(param); + + if (!param.isPositionalAllowed) { + this.hasNamedParameters = true; + } }, this); usingGroups = true; } }, this); } canon.Command = Command; @@ -9815,16 +9824,19 @@ Completer.prototype._getCompleterTemplat // We generate an array of emptyParameter markers for each positional // parameter to the current command. // Generally each emptyParameter marker begins with a space to separate it // from whatever came before, unless what comes before ends in a space. // Also if we've got a directTabText prediction or we're in a NamedParameter // then we don't want any text for that parameter at all. // The algorithm to add spaces needs to take this into account. + var command = this.requisition.commandAssignment.value; + var jsCommand = command && command.name === '{'; + var firstBlankParam = true; var emptyParameters = []; this.requisition.getAssignments().forEach(function(assignment) { if (!assignment.param.isPositionalAllowed) { return; } if (current.arg.type === 'NamedArgument') { return; @@ -9851,18 +9863,33 @@ Completer.prototype._getCompleterTemplat if (!trailingSeparator || !firstBlankParam) { text = '\u00a0' + text; // i.e. } firstBlankParam = false; emptyParameters.push(text); }.bind(this)); - var command = this.requisition.commandAssignment.value; - var jsCommand = command && command.name === '{'; + var optionsRemaining = false; + if (command && command.hasNamedParameters) { + command.params.forEach(function(param) { + var arg = this.requisition.getAssignment(param.name).arg; + if (!param.isPositionalAllowed && !param.hidden + && arg.type === "BlankArgument") { + optionsRemaining = true; + } + }, this); + } + + if (optionsRemaining) { + // Add an nbsp if we don't have one at the end of the input or if + // this isn't the first param we've mentioned + var prefix = (!trailingSeparator || !firstBlankParam) ? '\u00a0' : ''; + emptyParameters.push(prefix + '[options]'); + } // Is the entered command a JS command with no closing '}'? // TWEAK: This code should be considered for promotion to Requisition var unclosedJs = jsCommand && this.requisition.getAssignment(0).arg.suffix.indexOf('}') === -1; // The text for the 'jump to scratchpad' feature, or '' if it is disabled var link = this.scratchpad && jsCommand ? this.scratchpad.linkText : '';
--- a/browser/devtools/commandline/test/browser_cmd_cookie.js +++ b/browser/devtools/commandline/test/browser_cmd_cookie.js @@ -32,17 +32,17 @@ function testCookieCommands() { typed: "cookie remove", status: "ERROR", emptyParameters: [ " <key>" ] }); DeveloperToolbarTest.checkInputStatus({ typed: "cookie set", status: "ERROR", - emptyParameters: [ " <key>", " <value>" ], + emptyParameters: [ " <key>", " <value>", " [options]" ], }); DeveloperToolbarTest.exec({ typed: "cookie set fruit banana", args: { key: "fruit", value: "banana", path: "/",
--- a/browser/devtools/commandline/test/browser_gcli_web.js +++ b/browser/devtools/commandline/test/browser_gcli_web.js @@ -189,17 +189,17 @@ define('gclitest/index', ['require', 'ex * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testCanon', 'gclitest/testCli', 'gclitest/testCompletion', 'gclitest/testExec', 'gclitest/testHelp', 'gclitest/testHistory', 'gclitest/testInputter', 'gclitest/testIncomplete', 'gclitest/testIntro', 'gclitest/testJs', 'gclitest/testKeyboard', 'gclitest/testPref', 'gclitest/testRequire', 'gclitest/testResource', 'gclitest/testScratchpad', 'gclitest/testSettings', 'gclitest/testSpell', 'gclitest/testSplit', 'gclitest/testTokenize', 'gclitest/testTooltip', 'gclitest/testTypes', 'gclitest/testUtil'], function(require, exports, module) { +define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testCanon', 'gclitest/testCli', 'gclitest/testCompletion', 'gclitest/testExec', 'gclitest/testHelp', 'gclitest/testHistory', 'gclitest/testInputter', 'gclitest/testIncomplete', 'gclitest/testIntro', 'gclitest/testJs', 'gclitest/testKeyboard', 'gclitest/testMenu', 'gclitest/testPref', 'gclitest/testRequire', 'gclitest/testResource', 'gclitest/testScratchpad', 'gclitest/testSettings', 'gclitest/testSpell', 'gclitest/testSplit', 'gclitest/testTokenize', 'gclitest/testTooltip', 'gclitest/testTypes', 'gclitest/testUtil'], function(require, exports, module) { // We need to make sure GCLI is initialized before we begin testing it require('gcli/index'); var examiner = require('test/examiner'); // It's tempting to want to unify these strings and make addSuite() do the // call to require(), however that breaks the build system which looks for @@ -210,16 +210,17 @@ define('gclitest/suite', ['require', 'ex examiner.addSuite('gclitest/testExec', require('gclitest/testExec')); examiner.addSuite('gclitest/testHelp', require('gclitest/testHelp')); examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory')); examiner.addSuite('gclitest/testInputter', require('gclitest/testInputter')); examiner.addSuite('gclitest/testIncomplete', require('gclitest/testIncomplete')); examiner.addSuite('gclitest/testIntro', require('gclitest/testIntro')); examiner.addSuite('gclitest/testJs', require('gclitest/testJs')); examiner.addSuite('gclitest/testKeyboard', require('gclitest/testKeyboard')); + examiner.addSuite('gclitest/testMenu', require('gclitest/testMenu')); examiner.addSuite('gclitest/testPref', require('gclitest/testPref')); examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire')); examiner.addSuite('gclitest/testResource', require('gclitest/testResource')); examiner.addSuite('gclitest/testScratchpad', require('gclitest/testScratchpad')); examiner.addSuite('gclitest/testSettings', require('gclitest/testSettings')); examiner.addSuite('gclitest/testSpell', require('gclitest/testSpell')); examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit')); examiner.addSuite('gclitest/testTokenize', require('gclitest/testTokenize')); @@ -1730,16 +1731,17 @@ exports.setup = function() { canon.addCommand(exports.tsnDeepDown); canon.addCommand(exports.tsnDeepDownNested); canon.addCommand(exports.tsnDeepDownNestedCmd); canon.addCommand(exports.tselarr); canon.addCommand(exports.tsm); canon.addCommand(exports.tsg); canon.addCommand(exports.tshidden); canon.addCommand(exports.tscook); + canon.addCommand(exports.tslong); }; exports.shutdown = function() { canon.removeCommand(exports.tsv); canon.removeCommand(exports.tsr); canon.removeCommand(exports.tse); canon.removeCommand(exports.tsj); canon.removeCommand(exports.tsb); @@ -1755,16 +1757,17 @@ exports.shutdown = function() { canon.removeCommand(exports.tsnDeepDown); canon.removeCommand(exports.tsnDeepDownNested); canon.removeCommand(exports.tsnDeepDownNestedCmd); canon.removeCommand(exports.tselarr); canon.removeCommand(exports.tsm); canon.removeCommand(exports.tsg); canon.removeCommand(exports.tshidden); canon.removeCommand(exports.tscook); + canon.removeCommand(exports.tslong); types.deregisterType(exports.optionType); types.deregisterType(exports.optionValue); }; exports.option1 = { type: types.getType('string') }; exports.option2 = { type: types.getType('number') }; @@ -2046,16 +2049,88 @@ exports.tscook = { description: 'tscookSecureDesc' } ] } ], exec: createExec('tscook') }; +exports.tslong = { + name: 'tslong', + description: 'long param tests to catch problems with the jsb command', + returnValue:'string', + params: [ + { + name: 'url', + type: 'string', + description: 'tslongUrlDesc' + }, + { + group: "tslongOptionsDesc", + params: [ + { + name: 'indentSize', + type: 'number', + description: 'tslongIndentSizeDesc', + defaultValue: 2 + }, + { + name: 'indentChar', + type: { + name: 'selection', + lookup: [ + { name: "space", value: " " }, + { name: "tab", value: "\t" } + ] + }, + description: 'tslongIndentCharDesc', + defaultValue: ' ', + }, + { + name: 'preserveNewlines', + type: 'boolean', + description: 'tslongPreserveNewlinesDesc' + }, + { + name: 'preserveMaxNewlines', + type: 'number', + description: 'tslongPreserveMaxNewlinesDesc', + defaultValue: -1 + }, + { + name: 'jslintHappy', + type: 'boolean', + description: 'tslongJslintHappyDesc' + }, + { + name: 'braceStyle', + type: { + name: 'selection', + data: ['collapse', 'expand', 'end-expand', 'expand-strict'] + }, + description: 'tslongBraceStyleDesc', + defaultValue: "collapse" + }, + { + name: 'noSpaceBeforeConditional', + type: 'boolean', + description: 'tslongNoSpaceBeforeConditionalDesc' + }, + { + name: 'unescapeStrings', + type: 'boolean', + description: 'tslongUnescapeStringsDesc' + } + ] + } + ], + exec: createExec('tslong') +}; + }); /* * Copyright 2012, Mozilla Foundation and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -2225,108 +2300,108 @@ exports.testActivate = function(options) arrowTabText: '', emptyParameters: [] }); helpers.setInput('tsg'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [ ' <solo>' ] + emptyParameters: [ ' <solo>', ' [options]' ] }); helpers.setInput('tsg '); helpers.check({ - emptyParameters: [], + emptyParameters: [ ' [options]' ], arrowTabText: '', directTabText: 'aaa' }); helpers.setInput('tsg a'); helpers.check({ - emptyParameters: [], + emptyParameters: [ ' [options]' ], arrowTabText: '', directTabText: 'aa' }); helpers.setInput('tsg b'); helpers.check({ - emptyParameters: [], + emptyParameters: [ ' [options]' ], arrowTabText: '', directTabText: 'bb' }); helpers.setInput('tsg d'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsg aa'); helpers.check({ - emptyParameters: [], + emptyParameters: [ ' [options]' ], arrowTabText: '', directTabText: 'a' }); helpers.setInput('tsg aaa'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsg aaa '); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ '[options]' ] }); helpers.setInput('tsg aaa d'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsg aaa dddddd'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsg aaa dddddd '); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ '[options]' ] }); helpers.setInput('tsg aaa "d'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsg aaa "d d'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsg aaa "d d"'); helpers.check({ directTabText: '', arrowTabText: '', - emptyParameters: [] + emptyParameters: [ ' [options]' ] }); helpers.setInput('tsn ex '); helpers.check({ directTabText: '', arrowTabText: '', emptyParameters: [] }); @@ -2911,17 +2986,17 @@ exports.testCompleted = function(options helpers.setInput('tsg -'); helpers.check({ input: 'tsg -', markup: 'VVVVI', cursor: 5, directTabText: '-txt1', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { solo: { value: undefined, status: 'INCOMPLETE' }, txt1: { value: undefined, status: 'VALID' }, bool: { value: undefined, status: 'VALID' }, txt2: { value: undefined, status: 'VALID' }, num: { value: undefined, status: 'VALID' } } }); @@ -2929,68 +3004,68 @@ exports.testCompleted = function(options helpers.pressTab(); helpers.check({ input: 'tsg --txt1 ', markup: 'VVVVIIIIIIV', cursor: 11, directTabText: '', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], // Bug 770830: '<txt1>', ' <solo>' + emptyParameters: [ '[options]' ], // Bug 770830: '<txt1>', ' <solo>' args: { solo: { value: undefined, status: 'INCOMPLETE' }, txt1: { value: undefined, status: 'INCOMPLETE' }, bool: { value: undefined, status: 'VALID' }, txt2: { value: undefined, status: 'VALID' }, num: { value: undefined, status: 'VALID' } } }); helpers.setInput('tsg --txt1 fred'); helpers.check({ input: 'tsg --txt1 fred', markup: 'VVVVVVVVVVVVVVV', directTabText: '', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], // Bug 770830: ' <solo>' + emptyParameters: [ ' [options]' ], // Bug 770830: ' <solo>' args: { solo: { value: undefined, status: 'INCOMPLETE' }, txt1: { value: 'fred', status: 'VALID' }, bool: { value: undefined, status: 'VALID' }, txt2: { value: undefined, status: 'VALID' }, num: { value: undefined, status: 'VALID' } } }); helpers.setInput('tscook key value --path path --'); helpers.check({ input: 'tscook key value --path path --', markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVII', directTabText: 'domain', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { key: { value: 'key', status: 'VALID' }, value: { value: 'value', status: 'VALID' }, path: { value: 'path', status: 'VALID' }, domain: { value: undefined, status: 'VALID' }, secure: { value: false, status: 'VALID' } } }); helpers.setInput('tscook key value --path path --domain domain --'); helpers.check({ input: 'tscook key value --path path --domain domain --', markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVII', directTabText: 'secure', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { key: { value: 'key', status: 'VALID' }, value: { value: 'value', status: 'VALID' }, path: { value: 'path', status: 'VALID' }, domain: { value: 'domain', status: 'VALID' }, secure: { value: false, status: 'VALID' } } }); @@ -2999,17 +3074,17 @@ exports.testCompleted = function(options exports.testCase = function(options) { helpers.setInput('tsg AA'); helpers.check({ input: 'tsg AA', markup: 'VVVVII', directTabText: '', arrowTabText: 'aaa', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { solo: { value: undefined, text: 'AA', status: 'INCOMPLETE' }, txt1: { value: undefined, status: 'VALID' }, bool: { value: undefined, status: 'VALID' }, txt2: { value: undefined, status: 'VALID' }, num: { value: undefined, status: 'VALID' } } }); @@ -3057,113 +3132,128 @@ exports.testHidden = function(options) { helpers.setInput('tshidden'); helpers.check({ input: 'tshidden', markup: 'VVVVVVVV', directTabText: '', arrowTabText: '', status: 'VALID', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: undefined, status: 'VALID' }, invisibleboolean: { value: undefined, status: 'VALID' } } }); helpers.setInput('tshidden --vis'); helpers.check({ input: 'tshidden --vis', markup: 'VVVVVVVVVIIIII', directTabText: 'ible', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: undefined, status: 'VALID' }, invisibleboolean: { value: undefined, status: 'VALID' } } }); helpers.setInput('tshidden --invisiblestrin'); helpers.check({ input: 'tshidden --invisiblestrin', markup: 'VVVVVVVVVEEEEEEEEEEEEEEEE', directTabText: '', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: undefined, status: 'VALID' }, invisibleboolean: { value: undefined, status: 'VALID' } } }); helpers.setInput('tshidden --invisiblestring'); helpers.check({ input: 'tshidden --invisiblestring', markup: 'VVVVVVVVVIIIIIIIIIIIIIIIII', directTabText: '', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: undefined, status: 'INCOMPLETE' }, invisibleboolean: { value: undefined, status: 'VALID' } } }); helpers.setInput('tshidden --invisiblestring x'); helpers.check({ input: 'tshidden --invisiblestring x', markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV', directTabText: '', arrowTabText: '', status: 'VALID', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: 'x', status: 'VALID' }, invisibleboolean: { value: undefined, status: 'VALID' } } }); helpers.setInput('tshidden --invisibleboolea'); helpers.check({ input: 'tshidden --invisibleboolea', markup: 'VVVVVVVVVEEEEEEEEEEEEEEEEE', directTabText: '', arrowTabText: '', status: 'ERROR', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: undefined, status: 'VALID' }, invisibleboolean: { value: undefined, status: 'VALID' } } }); helpers.setInput('tshidden --invisibleboolean'); helpers.check({ input: 'tshidden --invisibleboolean', markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV', directTabText: '', arrowTabText: '', status: 'VALID', - emptyParameters: [ ], + emptyParameters: [ ' [options]' ], args: { visible: { value: undefined, status: 'VALID' }, invisiblestring: { value: undefined, status: 'VALID' }, invisibleboolean: { value: true, status: 'VALID' } } }); + + helpers.setInput('tshidden --visible xxx'); + helpers.check({ + input: 'tshidden --visible xxx', + markup: 'VVVVVVVVVVVVVVVVVVVVVV', + directTabText: '', + arrowTabText: '', + status: 'VALID', + emptyParameters: [ ], + args: { + visible: { value: 'xxx', status: 'VALID' }, + invisiblestring: { value: undefined, status: 'VALID' }, + invisibleboolean: { value: undefined, status: 'VALID' } + } + }); }; }); /* * Copyright 2012, Mozilla Foundation and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -3594,16 +3684,66 @@ exports.testIncrDecr = function() { check('tselarr 2', KEY_DOWNS_TO, 'tselarr 3'); check('tselarr 3', KEY_DOWNS_TO, 'tselarr 1'); check('tselarr 3', KEY_UPS_TO, 'tselarr 2'); }; }); /* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('gclitest/testMenu', ['require', 'exports', 'module' , 'test/assert', 'gclitest/helpers', 'gclitest/mockCommands'], function(require, exports, module) { + + +var test = require('test/assert'); +var helpers = require('gclitest/helpers'); +var mockCommands = require('gclitest/mockCommands'); + + +exports.setup = function(options) { + mockCommands.setup(); + helpers.setup(options); +}; + +exports.shutdown = function(options) { + mockCommands.shutdown(); + helpers.shutdown(options); +}; + +exports.testOptions = function(options) { + helpers.setInput('tslong'); + helpers.check({ + input: 'tslong', + markup: 'VVVVVV', + directTabText: '', + arrowTabText: '', + status: 'ERROR', + emptyParameters: [ ' <url>', ' [options]' ], + args: { + url: { value: undefined, status: 'INCOMPLETE' }, + indentSize: { value: undefined, status: 'VALID' }, + indentChar: { value: undefined, status: 'VALID' }, + preserveNewlines: { value: undefined, status: 'VALID' }, + preserveMaxNewlines: { value: undefined, status: 'VALID' }, + jslintHappy: { value: undefined, status: 'VALID' }, + braceStyle: { value: undefined, status: 'VALID' }, + noSpaceBeforeConditional: { value: undefined, status: 'VALID' }, + unescapeStrings: { value: undefined, status: 'VALID' } + } + }); +}; + + +}); + +/* * Copyright 2012, Mozilla Foundation and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -5711,16 +5851,17 @@ let testModuleNames = [ 'gclitest/testExec', 'gclitest/testHelp', 'gclitest/testHistory', 'gclitest/testInputter', 'gclitest/testIncomplete', 'gclitest/testIntro', 'gclitest/testJs', 'gclitest/testKeyboard', + 'gclitest/testMenu', 'gclitest/testPref', 'gclitest/mockSettings', 'gclitest/testRequire', 'gclitest/requirable', 'gclitest/testResource', 'gclitest/testScratchpad', 'gclitest/testSettings', 'gclitest/testSpell',