diff --git a/.travis.yml b/.travis.yml index b9dbe9b9..5f0328b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,12 @@ language: node_js sudo: false node_js: - '0.12' + - '4.2' + - '5.3' cache: directories: - - $(npm root -g) + - "$(npm root -g)" + - node_modules notifications: email: - devs-deep@mitocgroup.com @@ -21,10 +24,8 @@ env: before_install: - npm install -g babel@5.8.19 - npm install -g browserify@11.2.0 - - npm install -g mocha@2.3.3 - - npm install -g mocha-babel@3.0.0 + - npm install -g mocha@2.3.4 - npm install -g istanbul@0.3.21 - - npm install -g istanbul-combine@0.3.0 - npm install -g isparta@3.1.0 - npm install -g codacy-coverage@1.1.3 - cp test/package.json . diff --git a/bin/_head.sh b/bin/_head.sh index 29b3763b..868e263b 100644 --- a/bin/_head.sh +++ b/bin/_head.sh @@ -9,7 +9,7 @@ publish_npm_package() { echo "Publishing "${name} if [ -z $2 ] || ! $2; then - cd $1 && rm -rf node_modules/ && npm install --production && ${npm} version $3 && ${npm} publish + cd $1 && rm -rf node_modules/ && npm install --production --no-bin-links --no-optional && ${npm} version $3 && ${npm} publish else cd $1 && ${npm} version $3 fi diff --git a/src/bin/commands/compile-prod.js b/src/bin/commands/compile-prod.js index 7115e9f9..6e929f0f 100644 --- a/src/bin/commands/compile-prod.js +++ b/src/bin/commands/compile-prod.js @@ -13,6 +13,7 @@ module.exports = function(mainPath) { var LambdaExtractor = require('../../lib.compiled/Helpers/LambdasExtractor').LambdasExtractor; var DepsTreeOptimizer = require('../../lib.compiled/NodeJS/DepsTreeOptimizer').DepsTreeOptimizer; var NpmInstall = require('../../lib.compiled/NodeJS/NpmInstall').NpmInstall; + var NpmInstallLibs = require('../../lib.compiled/NodeJS/NpmInstallLibs').NpmInstallLibs; var NpmPrune = require('../../lib.compiled/NodeJS/NpmPrune').NpmPrune; var NpmDedupe = require('../../lib.compiled/NodeJS/NpmDedupe').NpmDedupe; var NpmRun = require('../../lib.compiled/NodeJS/NpmRun').NpmRun; @@ -25,6 +26,7 @@ module.exports = function(mainPath) { var tmp = require('tmp'); var removeSource = this.opts.locate('remove-source').exists; + var installSdk = this.opts.locate('aws-sdk').exists; var microservicesToDeploy = this.opts.locate('partial').value; if (mainPath.indexOf('/') !== 0) { @@ -246,41 +248,60 @@ module.exports = function(mainPath) { if (result.failed) { console.error(result.error); } else { - console.log('Removed aws-sdk@* in ' + lambdaTmpPath); + console.log('Cleanup Lambda sources in ' + lambdaTmpPath); } - var outputFile = path.join( - lambdaPath, - '..', - path.basename(lambdaPath) + '.zip' - ); - - console.log('Packing Lambda code into ' + outputFile + ' (' + lambdaTmpPath + ')'); - - // @todo: replace this with a node native - var zip = new Exec( - Bin.resolve('zip'), - '-y', - '-r', - outputFile, - '.' - ); - - zip.cwd = lambdaTmpPath; - zip.avoidBufferOverflow(); - - zip.run(function(result) { - if (result.failed) { - console.error(result.error); - this.exit(1); - } + if (installSdk) { + console.log('Installing latest aws-sdk into ' + lambdaTmpPath); + + var npmLink = new NpmInstallLibs(lambdaTmpPath); + npmLink.libs = 'aws-sdk'; - remaining--; - }.bind(this)); + npmLink.run(function() { + packSingle.bind(this)(lambdaPath, lambdaTmpPath, function() { + remaining--; + }.bind(this)); + }.bind(this)); + } else { + packSingle.bind(this)(lambdaPath, lambdaTmpPath, function() { + remaining--; + }.bind(this)); + } }.bind(this, lambdaPath, lambdaTmpPath)); } } + function packSingle(lambdaPath, lambdaTmpPath, cb) { + var outputFile = path.join( + lambdaPath, + '..', + path.basename(lambdaPath) + '.zip' + ); + + console.log('Packing Lambda code into ' + outputFile + ' (' + lambdaTmpPath + ')'); + + // @todo: replace this with a node native + var zip = new Exec( + Bin.resolve('zip'), + '-y', + '-r', + outputFile, + '.' + ); + + zip.cwd = lambdaTmpPath; + zip.avoidBufferOverflow(); + + zip.run(function(result) { + if (result.failed) { + console.error(result.error); + this.exit(1); + } + + cb(); + }.bind(this)); + } + function getMicroservicesToDeploy() { if (!microservicesToDeploy) { return []; diff --git a/src/bin/commands/deploy.js b/src/bin/commands/deploy.js index 7d450a50..946e5d1a 100644 --- a/src/bin/commands/deploy.js +++ b/src/bin/commands/deploy.js @@ -18,6 +18,7 @@ module.exports = function(mainPath) { var S3Service = require('deep-package-manager').Provisioning_Service_S3Service; var ProvisioningCollisionsDetectedException = require('deep-package-manager').Property_Exception_ProvisioningCollisionsDetectedException; + var installSdk = this.opts.locate('aws-sdk').exists; var localOnly = this.opts.locate('dry-run').exists; var fastDeploy = this.opts.locate('fast').exists; var dumpCodePath = this.opts.locate('dump-local').value; @@ -201,7 +202,8 @@ module.exports = function(mainPath) { ); !fastDeploy && cmd.addArg('--remove-source'); - microservicesToDeploy && cmd.addArg('--partial'); + microservicesToDeploy && cmd.addArg('--partial ' + microservicesToDeploy); + installSdk && cmd.addArg('--aws-sdk'); cmd.run(function(result) { if (result.failed) { diff --git a/src/bin/commands/install.js b/src/bin/commands/install.js index 8ac397b7..65345e98 100644 --- a/src/bin/commands/install.js +++ b/src/bin/commands/install.js @@ -33,7 +33,7 @@ module.exports = function(microserviceRepo, dumpPath) { prompt.readConfirm(function(result) { if (result) { - console.log('Start preparing for production'); + console.log('Start initializing backend...'); var cmd = new Exec( Bin.node, diff --git a/src/bin/commands/server.js b/src/bin/commands/server.js index 41ca3e5c..6680af0c 100644 --- a/src/bin/commands/server.js +++ b/src/bin/commands/server.js @@ -28,7 +28,6 @@ module.exports = function(mainPath) { var openBrowser = this.opts.locate('open-browser').exists; var skipBuildHook = this.opts.locate('skip-build-hook').exists; var skipBackendBuild = this.opts.locate('skip-backend-build').exists; - var profiling = this.opts.locate('profiling').exists; var skipFrontendBuild = this.opts.locate('skip-frontend-build').exists; // @todo: implement it in a better way @@ -55,7 +54,6 @@ module.exports = function(mainPath) { if (skipBackendBuild) { server = new Server(property); - server.profiling = profiling; startServer(); return; @@ -68,35 +66,32 @@ module.exports = function(mainPath) { property.runInitMsHooks(function() { server = new Server(property); - server.profiling = profiling; var lambdasToInstall = LambdaExtractor .createFromServer(server) .extract(); - runInstallHook(function() { - console.log('Running "npm install" on ' + lambdasToInstall.length + ' Lambdas'); + console.log('Running "npm install" on ' + lambdasToInstall.length + ' Lambdas'); - var npmInstall = new NpmInstall(lambdasToInstall); + var npmInstall = new NpmInstall(lambdasToInstall); - npmInstall.runChunk(function() { - if (Bin.npmModuleInstalled('aws-sdk', true)) { - console.log('Start linking aws-sdk'); + npmInstall.runChunk(function() { + if (Bin.npmModuleInstalled('aws-sdk', true)) { + console.log('Start linking aws-sdk'); + + linkAwsSdk.bind(this)(lambdasToInstall, startServer); + } else { + var awsSdkInstall = new NpmInstallLibs(); + awsSdkInstall.libs = 'aws-sdk'; + awsSdkInstall.global = true; + + awsSdkInstall.run(function() { + console.log('Installing aws-sdk globally'); linkAwsSdk.bind(this)(lambdasToInstall, startServer); - } else { - var awsSdkInstall = new NpmInstallLibs(); - awsSdkInstall.libs = 'aws-sdk'; - awsSdkInstall.global = true; - - awsSdkInstall.run(function() { - console.log('Installing aws-sdk globally'); - - linkAwsSdk.bind(this)(lambdasToInstall, startServer); - }.bind(this)); - } - }.bind(this), NpmInstall.DEFAULT_CHUNK_SIZE); - }.bind(this)); + }.bind(this)); + } + }.bind(this), NpmInstall.DEFAULT_CHUNK_SIZE); }.bind(this)); }.bind(this)); @@ -109,32 +104,6 @@ module.exports = function(mainPath) { }.bind(this)); } - function runInstallHook(cb) { - if (skipBuildHook) { - cb(); - return; - } - - var hookPath = path.join(mainPath, 'hook.server.js'); - - console.log('Checking for build hook in ' + hookPath); - - if (!fs.existsSync(hookPath)) { - cb(); - return; - } - - console.log('Running build hook from ' + hookPath); - - var hook = require(hookPath); - - if (typeof hook === 'function') { - hook.bind(server)(cb); - } else { - cb(); - } - } - function startServer() { if (buildPath) { server.buildPath = buildPath; diff --git a/src/bin/manifest.js b/src/bin/manifest.js index d039347b..24d6f907 100644 --- a/src/bin/manifest.js +++ b/src/bin/manifest.js @@ -28,7 +28,7 @@ module.exports = { }, 'install': { example: 'deepify install https://github.com/MitocGroup/deep-microservices-todo-app.git path/to/web_app', - description: 'Installs an microservice from remote git repository', + description: 'Install an microservice from remote git repository', opts: { }, args: { @@ -46,11 +46,6 @@ module.exports = { example: 'deepify server path/to/web_app -o', description: 'Run local development server', opts: { - profiling: { - alias: 'd', - description: 'Enable Lambdas profiling', - required: false, - }, 'build-path': { alias: 'b', description: 'The path to the build (in order to pick up config)', @@ -128,6 +123,11 @@ module.exports = { description: 'Faster deployment without copying the sources (may alter the web app state)', required: false, }, + 'aws-sdk': { + alias: 'a', + description: 'Force latest aws-sdk in Lambda', + required: false, + }, }, args: { path: { @@ -182,7 +182,7 @@ module.exports = { }, 'compile-es6': { example: 'deepify compile-es6 path/to/lambda', - description: 'Compiles ES6 scripts to ES5 using babel (matched by *.es6)', + description: 'Compile ES6 scripts to ES5 using babel (matched by *.es6)', opts: { }, args: { @@ -206,6 +206,11 @@ module.exports = { description: 'Partial deploy (one or several comma separated microservices identifiers)', required: false, }, + 'aws-sdk': { + alias: 'a', + description: 'Force latest aws-sdk in Lambda', + required: false, + }, }, args: { path: { diff --git a/src/hooks/assure_deep_dev.js b/src/hooks/assure_deep_dev.js deleted file mode 100755 index 6b93c5e7..00000000 --- a/src/hooks/assure_deep_dev.js +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env node -/** - * Created by AlexanderC on 8/13/15. - * - * @todo: reuse this script from deep-framework - */ - -// hook to make jscs tests pass! -var npmEnvKey = 'npm_config_production'; - -// @todo: populate ignores this dynamically -var skipModules = [ - 'mocha', 'chai', 'sinon', - 'sinon-chai', 'istanbul', - 'jscoverage', 'jshint', 'jshint-stylish', -]; - -if (process.env[npmEnvKey] !== 'true') { - var path = require('path'); - var fs = require('fs'); - var exec = require('child_process').exec; - - var deepModulePath = path.join(__dirname, '../node_modules'); - - fs.readdir(deepModulePath, function (error, files) { - if (error) { - console.error('Error while listing deep modules: ' + error); - process.exit(1); - } - - for (var i = 0; i < files.length; i++) { - var basename = files[i]; - - if (['.', '..'].indexOf(basename) === -1 && basename.indexOf('deep-') === 0) { - var modulePath = path.join(deepModulePath, basename); - - fs.stat(modulePath, function (modulePath, error, stats) { - if (error) { - console.error('Error while getting stats of ' + modulePath + ': ' + error); - process.exit(1); - } - - if (stats.isDirectory()) { - var packageFile = path.join(modulePath, 'package.json'); - - fs.readFile(packageFile, function (error, data) { - if (error) { - console.error('Error while reading ' + packageFile + ': ' + error); - process.exit(1); - } - - var packageConfig = JSON.parse(data.toString()); - - if (!packageConfig) { - console.error('Broken JSON string in ' + packageFile + ': ' + error); - process.exit(1); - } - - var pckgsToInstall = []; - - var devDependencies = packageConfig.devDependencies || {}; - - for (var depName in devDependencies) { - if (!devDependencies.hasOwnProperty(depName)) { - continue; - } - - if (skipModules.indexOf(depName) !== -1) { - continue; - } - - var depVersion = devDependencies[depName]; - var depString = depName + '@' + depVersion; - - console.log('Adding NPM package ' + depString + ' to installation queue'); - - pckgsToInstall.push(depString); - } - - if (pckgsToInstall.length > 0) { - var installCmd = 'cd ' + modulePath + ' && npm install ' + pckgsToInstall.join(' '); - - console.log('Running: ' + installCmd); - - exec(installCmd + ' &>/dev/null', function (error) { - if (error) { - console.error('Error while installing npm packages ' + pckgsToInstall.join(', ') + ': ' + error); - return; - } - - console.log('The following NPM packages have been installed ' + pckgsToInstall.join(', ')); - }.bind(this)); - } - }.bind(this)); - } - }.bind(this, modulePath)); - } - } - }); -} diff --git a/src/lib/Helpers/Exec.js b/src/lib/Helpers/Exec.js index ae210c8e..2a02aa24 100644 --- a/src/lib/Helpers/Exec.js +++ b/src/lib/Helpers/Exec.js @@ -4,314 +4,13 @@ 'use strict'; -import ChildProcess from 'child_process'; -import syncExec from 'sync-exec'; -import {EventEmitter} from 'events'; +import {Helpers_Exec as BaseExec} from 'deep-package-manager'; -export class Exec { +export class Exec extends BaseExec { /** - * @param {String} cmd - * @param {String|*} args + * @param {*} args */ - constructor(cmd, ...args) { - this._cmd = cmd; - this._args = args; - - this._error = null; - this._isExec = false; - this._devNull = false; - this._result = null; - - this._cwd = process.cwd(); - } - - /** - * @returns {String} - */ - get cwd() { - return this._cwd; - } - - /** - * @param {String} path - */ - set cwd(path) { - this._cwd = path; - } - - /** - * @returns {String|null} - */ - get result() { - this._assureCmdExecuted(); - - return this._result; - } - - /** - * @returns {Boolean} - */ - get succeed() { - return !this.error; - } - - /** - * @returns {Boolean} - */ - get failed() { - return !!this.error; - } - - /** - * @returns {String|Error|null} - */ - get error() { - this._assureCmdExecuted(); - - return this._error; - } - - /** - * @returns {Exec} - */ - avoidBufferOverflow() { - this._devNull = true; - - return this; - } - - /** - * @returns {String} - */ - get cmd() { - return this._cmd; - } - - /** - * @returns {Array} - */ - get args() { - return this._args; - } - - /** - * @param {String} arg - * @returns {Exec} - */ - addArg(arg) { - this._args.push(arg); - - return this; - } - - /** - * @returns {Exec} - */ - runSync() { - this._isExec = true; - - let result = syncExec(this._fullCmd, { - cwd: this._cwd, - }); - - this._checkError(result.status); - this._result = result.stdout ? result.stdout.toString().trim() : null; - - return this; - } - - /** - * @param {Function} cb - * @param {Boolean} pipeOutput - * @returns {Exec} - */ - run(cb, pipeOutput = false) { - this._isExec = true; - - if (pipeOutput) { - return this._spawn(cb); - } - - return this._exec(cb); - } - - /** - * @param {Boolean} increase - * @param {EventEmitter|*} emitters - * @private - */ - static _tweakProcessListeners(increase = true, ...emitters) { - /** - * @type {EventEmitter[]} - */ - emitters = [ - process, - process.stdout, - process.stderr, - process.stdin, - ].concat(emitters); - - for (let i in emitters) { - if (!emitters.hasOwnProperty(i)) { - continue; - } - - let emitter = emitters[i]; - - if (!emitter.hasOwnProperty('getMaxListeners')) { - emitter.__max_listeners__ = EventEmitter.defaultMaxListeners || 0; - - emitter.getMaxListeners = () => { - return emitter.__max_listeners__; - }; - } - - if (increase) { - emitter.setMaxListeners(emitter.getMaxListeners() + 1); - - if (emitter.hasOwnProperty('__max_listeners__')) { - emitter.__max_listeners__++; - } - } else { - emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0)); - - if (emitter.hasOwnProperty('__max_listeners__')) { - emitter.__max_listeners__--; - } - } - } - } - - /** - * @param {Function} cb - * @returns {Exec} - * @private - */ - _spawn(cb) { - let cmdParts = this._cmd.trim().split(' '); - let realCmd = cmdParts.shift(); - let realArgs = cmdParts.concat(this._args); - let uncaughtError = false; - - let proc = ChildProcess.spawn(realCmd, realArgs, { - cwd: this._cwd, - stdio: [process.stdin, 'pipe', 'pipe'], - }); - - Exec._tweakProcessListeners(true, proc); - - proc.stdout.pipe(process.stdout); - proc.stderr.pipe(process.stderr); - - proc.stdout.on('data', (data) => { - if (!this._result) { - this._result = ''; - } - - this._result += data.toString(); - }); - - proc.on('uncaughtException', (error) => { - uncaughtError = true; - - Exec._tweakProcessListeners(false, proc); - - this._error = error; - - cb(this); - }); - - proc.on('close', (code) => { - if (uncaughtError) { - return; - } - - Exec._tweakProcessListeners(false, proc); - - this._checkError(code); - - if (this._result) { - this._result = this._result.trim(); - } - - cb(this); - }); - - return this; - } - - /** - * @param {Function} cb - * @returns {Exec} - * @private - */ - _exec(cb) { - ChildProcess.exec(this._fullCmd, { - cwd: this._cwd, - }, (error, stdout) => { - if (error) { - this._error = new Error( - `Command '${this._fullCmd}' failed in '${this._cwd}' with error: ${error}` - ); - } else { - this._result = stdout ? stdout.toString().trim() : null; - } - - cb(this); - }); - - return this; - } - - /** - * @param {String|Number} code - * @private - */ - _checkError(code) { - if (parseInt(code) !== 0) { - this._error = new Error(`Command '${this._fullCmd}' failed in '${this._cwd}' with exit code ${code}`); - } - } - - /** - * @returns {String} - * @private - */ - get _fullCmd() { - let suffix = this._internalCmdSuffix; - let cmd = `${this._cmd} ${this._args.join(' ')}`; - - cmd = cmd.split(';').join(` ${suffix}; `); - cmd = cmd.split('&&').join(` ${suffix}; `); - cmd = cmd.split('||').join(` ${suffix}; `); - - cmd += suffix; - cmd = cmd.replace(new RegExp(`(${Exec.PIPE_VOID})+`), Exec.PIPE_VOID); - - return cmd.trim(); - } - - /** - * @returns {String} - * @private - */ - get _internalCmdSuffix() { - return this._devNull ? Exec.PIPE_VOID : ''; - } - - /** - * @private - */ - _assureCmdExecuted() { - if (!this._isExec) { - throw new Error(`Command '${this._fullCmd}' is not yet executed (cwd: '${this._cwd}')`); - } - } - - /** - * @returns {String} - */ - static get PIPE_VOID() { - return ' > /dev/null 2>&1'; + constructor(...args) { + super(...args); } } diff --git a/src/lib/Lambda/Profile/AbstractProfiler.js b/src/lib/Lambda/Profile/AbstractProfiler.js deleted file mode 100644 index 16cf2afb..00000000 --- a/src/lib/Lambda/Profile/AbstractProfiler.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Created by AlexanderC on 8/17/15. - */ - -'use strict'; - -import Core from 'deep-core'; -import FileSystem from 'fs'; -import FileSystemExtra from 'fs-extra'; -import Path from 'path'; -import {Helpers_Hash as Hash} from 'deep-package-manager'; -import OS from 'os'; - -export class AbstractProfiler extends Core.OOP.Interface { - /** - * @param {String} name - */ - constructor(name = null) { - super(['start', 'stop']); - - this._profilesPath = AbstractProfiler._tmpDir; - - FileSystemExtra.ensureDirSync(this._profilesPath); - - this._name = null; - this._lastProfile = null; - - this.name = name || Hash.pseudoRandomId(this._lambda); - } - - /** - * @returns {String} - * @private - */ - static get _tmpDir() { - return Path.join( - OS.tmpdir(), - `__deep_profiling-${process.pid}` - ); - } - - /** - * @param {String} name - * @param {String} rootPath - * @returns {String} - */ - static getDumpFile(name, rootPath = null) { - return Path.join(rootPath || AbstractProfiler._tmpDir, `${Hash.md5(name)}${AbstractProfiler.EXTENSION}`); - } - - /** - * @returns {String} - */ - get name() { - return this._name; - } - - /** - * @param {String} name - */ - set name(name) { - this._name = name; - this._dumpFile = AbstractProfiler.getDumpFile(name, this._profilesPath); - } - - /** - * @returns {String} - */ - get dumpFile() { - return this._dumpFile; - } - - /** - * @param {Object} profileData - */ - set profile(profileData) { - this._lastProfile = profileData; - } - - /** - * @returns {Object} - */ - get profile() { - return this._lastProfile; - } - - /** - * @returns {String} - */ - get profilePlain() { - return JSON.stringify(this.profile, null, 2); - } - - /** - * @param {Function} callback - */ - save(callback) { - FileSystem.writeFile( - this.dumpFile, - this.profilePlain, - 'utf8', - function(error) { - callback(error, this.dumpFile); - }.bind(this) - ); - } - - /** - * @returns {String} - * @constructor - */ - static get EXTENSION() { - return '.cpuprofile'; - } -} diff --git a/src/lib/Lambda/Profile/Profiler.js b/src/lib/Lambda/Profile/Profiler.js deleted file mode 100644 index 0af6f462..00000000 --- a/src/lib/Lambda/Profile/Profiler.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Created by AlexanderC on 8/17/15. - */ - -'use strict'; - -import {AbstractProfiler} from './AbstractProfiler'; -import V8Profiler from './v8ProfilerFallback'; -import TraceViewConverter from 'traceviewify'; - -export class Profiler extends AbstractProfiler { - /** - * @param {String} name - */ - constructor(name = null) { - super(name); - } - - /** - * Start profiling - */ - start() { - V8Profiler.startProfiling(this._name); - } - - /** - * Stop profiling - */ - stop() { - let profile = V8Profiler.stopProfiling(this._name); - - if (!profile) { - this._lastProfile = {}; - return; - } - - this._lastProfile = TraceViewConverter(Profiler._normalizeProfile(profile)); - - profile.delete(); - } - - /** - * @param {CpuProfile} profile - * @returns {Object} - * @private - */ - static _normalizeProfile(profile) { - return JSON.parse(JSON.stringify(profile, null, 2)); - } -} diff --git a/src/lib/Lambda/Profile/StaticDumpFileProfiler.js b/src/lib/Lambda/Profile/StaticDumpFileProfiler.js deleted file mode 100644 index dc89e864..00000000 --- a/src/lib/Lambda/Profile/StaticDumpFileProfiler.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Created by AlexanderC on 8/18/15. - */ - -'use strict'; - -import {Profiler} from './Profiler'; - -export class StaticDumpFileProfiler extends Profiler { - /** - * @param {String} name - * @param {String} staticDumpFile - */ - constructor(name = null, staticDumpFile = null) { - super(name); - - this._staticDumpFile = staticDumpFile; - } - - /** - * @param {String} path - */ - set staticDumpFile(path) { - this._staticDumpFile = path; - } - - /** - * @returns {String} - */ - get staticDumpFile() { - return this._staticDumpFile; - } - - /** - * @returns {String} - */ - get dumpFile() { - return this._staticDumpFile; - } -} diff --git a/src/lib/Lambda/Profile/v8ProfilerFallback.js b/src/lib/Lambda/Profile/v8ProfilerFallback.js deleted file mode 100644 index 7b157760..00000000 --- a/src/lib/Lambda/Profile/v8ProfilerFallback.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Created by AlexanderC on 11/30/15. - */ - -'use strict'; - -export default getV8Profiler(); - -function getV8Profiler() { - let profiler = null; - - try { - // @todo: avoid logged errors - profiler = require('v8-profiler'); - } catch(e) { - profiler = { - startProfiling: () => { - }, - stopProfiling: () => { - return null; - }, - }; - } - - return profiler; -} diff --git a/src/lib/Lambda/Runtime.js b/src/lib/Lambda/Runtime.js index 4052df5e..dabe8ef8 100644 --- a/src/lib/Lambda/Runtime.js +++ b/src/lib/Lambda/Runtime.js @@ -33,7 +33,6 @@ export class Runtime { this._timer = null; this._silent = false; - this._profiler = null; this._name = Hash.pseudoRandomId(this); this._lambdaPath = lambdaPath; this._awsConfigFile = null; @@ -104,20 +103,6 @@ export class Runtime { this._name = name; } - /** - * @returns {AbstractProfiler} - */ - get profiler() { - return this._profiler; - } - - /** - * @param {AbstractProfiler} profiler - */ - set profiler(profiler) { - this._profiler = profiler; - } - /** * @returns {Boolean} */ @@ -155,7 +140,6 @@ export class Runtime { } this._measureTime && this._timer.start(); - this._profiler && this._profiler.start(); this._lambda.handler.bind(this)(event, this.context); @@ -177,21 +161,12 @@ export class Runtime { let lambda = Runtime.createLambda(localPath, _this._awsConfigFile); lambda.name = data.lambda; - lambda.profiler = _this._profiler; lambda.succeed = (result) => { - lambda.profiler && lambda.profiler.save((error) => { - error && _this._log(`Error while saving profile for Lambda ${lambda.name}: ${error}`); - }); - callback(null, result); }; lambda.fail = (error) => { - lambda.profiler && lambda.profiler.save((error) => { - error && _this._log(`Error while saving profile for Lambda ${lambda.name}: ${error}`); - }); - callback(error, null); }; @@ -293,13 +268,25 @@ export class Runtime { * @returns {Object} */ get context() { + let date = new Date(); + let logStreamDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`; + return { + + /** make the context Lambda alike */ + awsRequestId: '6bde10dc-a329-11e5-8f4d-55470b0a5783', + invokeid: '6bde10dc-a329-11e5-8f4d-55470b0a5783', + logGroupName: `/aws/lambda/${this._name}`, + logStreamName: `${logStreamDate}/${logStreamDate}[$LATEST]e680b516b0ea402eb3ff38f10b40a264`, + functionName: this._name, + memoryLimitInMB: '128', + functionVersion: '$LATEST', + invokedFunctionArn: `arn:aws:lambda:::function:${this._name}`, + clientContext: { EnvironmentName: Runtime.ENVIRONMENT, }, succeed: function(result) { - this._profiler && this._profiler.stop(); - this._succeed(result); this._measureTime && this._log(this._timer.stop().toString()); @@ -307,8 +294,6 @@ export class Runtime { this._complete(null, result); }.bind(this), fail: function(error) { - this._profiler && this._profiler.stop(); - this._fail(error); this._measureTime && this._log(this._timer.stop().toString()); diff --git a/src/lib/Lambda/Thread.js b/src/lib/Lambda/Thread.js index 0cb5c79b..703d9659 100644 --- a/src/lib/Lambda/Thread.js +++ b/src/lib/Lambda/Thread.js @@ -75,10 +75,6 @@ export class Thread { contextSent = true; - if (this._runtime.profiler) { - this._runtime.profiler.profile = payload.profile; - } - this._runtime[payload.state].apply(this._runtime, payload.args); this._cleanup(); }); diff --git a/src/lib/Lambda/thread_wrapper.js b/src/lib/Lambda/thread_wrapper.js index f2ae7f30..c2a44eca 100644 --- a/src/lib/Lambda/thread_wrapper.js +++ b/src/lib/Lambda/thread_wrapper.js @@ -6,7 +6,6 @@ import {Runtime} from './Runtime'; import {ForksManager} from './ForksManager'; -import {StaticDumpFileProfiler} from '../Lambda/Profile/StaticDumpFileProfiler'; // avoid process to be killed when some async calls are still active! ForksManager.registerListener(); @@ -22,13 +21,6 @@ let rawRuntime = JSON.parse(args[0]); let runtime = Runtime.createLambda(rawRuntime._lambdaPath, rawRuntime._awsConfigFile); runtime.name = rawRuntime._name; -if (rawRuntime._profiler) { - runtime.profiler = new StaticDumpFileProfiler( - rawRuntime._profiler._name, - rawRuntime._profiler._dumpFile - ); -} - /** * * @param {Runtime} runtime @@ -54,7 +46,6 @@ if (rawRuntime._profiler) { if (assureContextNotSent(result)) { process.send({ state: 'succeed', - profile: runtime.profiler ? runtime.profiler.profile : null, args: [result], }); } @@ -64,7 +55,6 @@ if (rawRuntime._profiler) { if (assureContextNotSent(error)) { process.send({ state: 'fail', - profile: runtime.profiler ? runtime.profiler.profile : null, args: [error], }); } diff --git a/src/lib/NodeJS/Bin.js b/src/lib/NodeJS/Bin.js index fa41055a..50a0c478 100644 --- a/src/lib/NodeJS/Bin.js +++ b/src/lib/NodeJS/Bin.js @@ -18,6 +18,26 @@ export class Bin { .succeed; } + /** + * @returns {Number} + */ + static get npmMajorVersion() { + let versionResult = new Exec(Bin.npm, '--version').runSync(); + + if (versionResult.failed) { + throw new Error(versionResult.error); + } + + return Number(versionResult.result.match(/^(\d+)\./)[1]); + } + + /** + * @returns {Number} + */ + static get nodeMajorVersion() { + return Number(process.version.match(/^v(\d+)\./)[1]); + } + /** * @returns {String} */ diff --git a/src/lib/NodeJS/DepsTreeOptimizer.js b/src/lib/NodeJS/DepsTreeOptimizer.js index 02241558..50220bd2 100644 --- a/src/lib/NodeJS/DepsTreeOptimizer.js +++ b/src/lib/NodeJS/DepsTreeOptimizer.js @@ -13,6 +13,7 @@ import {_extend as extend} from 'util'; import {Exec} from '../Helpers/Exec'; import gatherDependencies from 'gather-dependencies'; import {UndefinedDepsResolver} from './UndefinedDepsResolver'; +import {Bin} from './Bin'; export class DepsTreeOptimizer { /** @@ -329,16 +330,17 @@ export class DepsTreeOptimizer { locker.run(() => { // @todo: fix missing deps (need all of them!) - //cb(this._readShrinkwrapFile()); - - // @todo: remove when fixed the issue above - gatherDependencies(this._path, (error, data) => { - if (error) { - throw error; - } + if (Bin.npmMajorVersion >= 3) { + cb(this._readShrinkwrapFile()); + } else { + gatherDependencies(this._path, (error, data) => { + if (error) { + throw error; + } - cb(data); - }); + cb(data); + }); + } }); return this; diff --git a/src/lib/NodeJS/UndefinedDepsResolver.js b/src/lib/NodeJS/UndefinedDepsResolver.js index 8f87744b..d7b3f5e1 100644 --- a/src/lib/NodeJS/UndefinedDepsResolver.js +++ b/src/lib/NodeJS/UndefinedDepsResolver.js @@ -75,6 +75,11 @@ export class UndefinedDepsResolver { this._cloneShadow = {}; this._resolvedStack = {}; + // @todo: remove? + if (process.env.hasOwnProperty('DEEP_DUMP_RESOLVED_DEPS_TREE')) { + console.log(this._mainDep.toString()); + } + cb(); }); @@ -93,16 +98,14 @@ export class UndefinedDepsResolver { } let suitableDep = this._mainDep.find(undefinedDep.name, resolvedVersion); - let shadowKey = `${undefinedDep.name}@${undefinedDep.requestedVersion}`; if (!suitableDep) { - let resolvedFullName = `${undefinedDep.name}@${resolvedVersion}`; - - throw new Error( - `Unable to find suitable dep for ${shadowKey} resolved into ${resolvedFullName}` - ); + remaining--; + return; } + let shadowKey = `${undefinedDep.name}@${undefinedDep.requestedVersion}`; + // @todo: set through an setter undefinedDep._version = suitableDep.version; this._cloneChildrenStack(suitableDep, undefinedDep); diff --git a/src/lib/Server/Hook.js b/src/lib/Server/Hook.js new file mode 100644 index 00000000..2eec4cdd --- /dev/null +++ b/src/lib/Server/Hook.js @@ -0,0 +1,146 @@ +/** + * Created by AlexanderC on 12/18/15. + */ + +'use strict'; + +import path from 'path'; +import fs from 'fs'; +import {Helpers_WaitFor as WaitFor} from 'deep-package-manager'; + +export class Hook { + /** + * @param {Server|*} server + */ + constructor(server) { + this._server = server; + } + + /** + * @returns {Server|*} + */ + get server() { + return this._server; + } + + /** + * @param {Function} callback + * @returns {Hook} + */ + runBefore(callback) { + return this.run(Hook.BEFORE, callback); + } + + /** + * @param {Function} callback + * @returns {Hook} + */ + runAfter(callback) { + return this.run(Hook.AFTER, callback); + } + + /** + * @param {String} type + * @param {Function} callback + * @returns {Hook} + */ + run(type, callback) { + let wait = new WaitFor(); + let microservices = this._server.property.microservices; + let remaining = microservices.length; + + wait.push(() => { + return remaining <= 0; + }); + + wait.ready(callback); + + for (let i in microservices) { + if (!microservices.hasOwnProperty(i)) { + continue; + } + + let microservice = microservices[i]; + + this._run(microservice, type, () => { + remaining--; + }); + } + + return this; + } + + /** + * @param {Microservice} microservice + * @param {String} type + * @param {Function} callback + * @returns {Hook} + * @private + */ + _run(microservice, type, callback) { + let hookFile = path.join(microservice.basePath, Hook.FILE_NAME); + + if (!fs.existsSync(hookFile)) { + console.log(`No "server ${type} init hook" found in ${microservice.identifier}`); + + callback(); + return this; + } + + console.log(`Running "server ${type} init hook" in ${microservice.identifier}`); + + let hook = require(hookFile); + + hook.bind(this._createContext(type))(callback); + } + + /** + * @param {String} type + * @returns {{isBefore: Function, isAfter: Function, server: (Server|*)}} + * @private + */ + _createContext(type) { + return { + + /** + * @returns {Boolean} + */ + isBefore: () => { + return type === Hook.BEFORE; + }, + + /** + * @returns {Boolean} + */ + isAfter: () => { + return type === Hook.AFTER; + }, + + /** + * @returns {Server|*} + */ + server: this._server, + }; + } + + /** + * @returns {String} + */ + static get BEFORE() { + return 'before'; + } + + /** + * @returns {String} + */ + static get AFTER() { + return 'after'; + } + + /** + * @returns {String} + */ + static get FILE_NAME() { + return 'hook.server.js'; + } +} diff --git a/src/lib/Server/Instance.js b/src/lib/Server/Instance.js index 79dfb0f3..60a73aa2 100644 --- a/src/lib/Server/Instance.js +++ b/src/lib/Server/Instance.js @@ -15,14 +15,13 @@ import OS from 'os'; import Mime from 'mime'; import JsonFile from 'jsonfile'; import {Runtime as LambdaRuntime} from '../Lambda/Runtime'; -import {Profiler} from '../Lambda/Profile/Profiler'; import QueryString from 'querystring'; -import {TraceBuilder} from './TraceBuilder'; import {Property_Instance as Property} from 'deep-package-manager'; import {Property_Frontend as Frontend} from 'deep-package-manager'; import {Microservice_Metadata_Action as Action} from 'deep-package-manager'; import {Property_Config as Config} from 'deep-package-manager'; import DeepDB from 'deep-db'; +import {Hook} from './Hook'; export class Instance { /** @@ -243,51 +242,60 @@ export class Instance { * @returns {Instance} */ listen(port = 8080, dbServer = null, callback = () => {}) { - this._log(`Creating server on port ${port}`); + let hook = new Hook(this); - this._server = Http.createServer((...args) => { - this._handler(...args); - }); + hook.runBefore(() => { + this._log(`Creating server on port ${port}`); - var localDbInstance = null; + this._server = Http.createServer((...args) => { + this._handler(...args); + }); - this._server.listen(port, (error) => { - if (error) { - throw new FailedToStartServerException(port, error); - } + var localDbInstance = null; - this._host = `http://localhost:${port}`; + this._server.listen(port, (error) => { + if (error) { + throw new FailedToStartServerException(port, error); + } - this._log('HTTP Server is up and running!'); + this._host = `http://localhost:${port}`; - if (!dbServer) { - callback(this); - return; - } + this._log('HTTP Server is up and running!'); - this._log(`Creating local DynamoDB instance on port ${DeepDB.LOCAL_DB_PORT}`); + if (!dbServer) { + hook.runAfter(() => { + callback(this); + }); - localDbInstance = DeepDB.startLocalDynamoDBServer((error) => { - if (error) { - throw new FailedToStartServerException(port, error); + return; } - this._log(`You can access DynamoDB Console via http://localhost:${DeepDB.LOCAL_DB_PORT}/shell`); + this._log(`Creating local DynamoDB instance on port ${DeepDB.LOCAL_DB_PORT}`); - callback(this); - }, dbServer); - }); + localDbInstance = DeepDB.startLocalDynamoDBServer((error) => { + if (error) { + throw new FailedToStartServerException(port, error); + } - // @todo: move it in destructor? - process.on('exit', () => { - this.stop(() => { - if (localDbInstance) { - localDbInstance.stop(() => { - process.exit(0); + this._log(`You can access DynamoDB Console via http://localhost:${DeepDB.LOCAL_DB_PORT}/shell`); + + hook.runAfter(() => { + callback(this); }); - } else { - process.exit(0); - } + }, dbServer); + }); + + // @todo: move it in destructor? + process.on('exit', () => { + this.stop(() => { + if (localDbInstance) { + localDbInstance.stop(() => { + process.exit(0); + }); + } else { + process.exit(0); + } + }); }); }); @@ -304,28 +312,6 @@ export class Instance { return this; } - /** - * @param {LambdaRuntime} lambda - * @private - */ - _trySaveProfile(lambda) { - // the second check is done because of threaded version! - if (!lambda.profiler || !lambda.profiler.profile) { - return; - } - - lambda.profiler.save((error) => { - if (error) { - this._log(`Error while saving profile for Lambda ${lambda.name}: ${error}`); - return; - } - - let profileUrl = `${this._host}${Instance.PROFILE_URI}?p=${lambda.name}`; - - this._log(`Profile for Lambda ${lambda.name} accessible at ${profileUrl}`); - }); - } - /** * @returns {Number} */ @@ -347,11 +333,8 @@ export class Instance { ); lambda.name = `${lambdaConfig.name}-${this.localId}`; - lambda.profiler = this._profiling ? new Profiler(lambda.name) : null; lambda.succeed = (result) => { - this._trySaveProfile(lambda); - let plainResult = JSON.stringify(result); if (!asyncMode) { @@ -363,8 +346,6 @@ export class Instance { }; lambda.fail = (error) => { - this._trySaveProfile(lambda); - if (!asyncMode) { this._log(`Lambda ${lambdaConfig.name} execution fail: ${error.message}`); this._send500(response, error); @@ -403,35 +384,6 @@ export class Instance { this._send(response, JSON.stringify(this._defaultFrontendConfig), 200, 'application/json'); return; } - } - - if (uri === Instance.PROFILE_URI) { - if (queryObject.p) { - // @todo: make it compatible with other browsers - if (!this._isTracerCompatible(request)) { - this._send(response, '

Try open profiling url in Chrome/Chromium browser

', 200, 'text/html', false); - return; - } - - let profileFile = Profiler.getDumpFile(queryObject.p); - let traceBuilder = new TraceBuilder(profileFile); - - traceBuilder.compile(function(error, file) { - if (error) { - this._log(`Unable to read profile ${profileFile}: ${error}`); - this._send500(response, error); - return; - } - - this._log(`Serving profile ${profileFile}`); - this._send(response, file, 200, 'text/html', true); - }.bind(this)); - - return; - } - - this._send500(response, 'You have to specify profile id'); - return; } else if (uri === Instance.LAMBDA_URI || uri === Instance.LAMBDA_ASYNC_URI) { let isAsync = uri === Instance.LAMBDA_ASYNC_URI; @@ -533,17 +485,6 @@ export class Instance { }.bind(this)); } - /** - * @param {Http.IncomingMessage} request - * @returns {Boolean} - * @private - */ - _isTracerCompatible(request) { - let ua = request.headers['user-agent'] || ''; - - return /chrom(e|ium)/i.test(ua); - } - /** * @param {Http.IncomingMessage} request * @param {Function} callback @@ -637,13 +578,6 @@ export class Instance { this._logger(...args); } - /** - * @returns {String} - */ - static get PROFILE_URI() { - return '/_/profile'; - } - /** * @returns {String} */ diff --git a/src/lib/Server/TraceBuilder.js b/src/lib/Server/TraceBuilder.js deleted file mode 100644 index 78332397..00000000 --- a/src/lib/Server/TraceBuilder.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Created by AlexanderC on 8/17/15. - */ - -'use strict'; - -import Path from 'path'; -import {exec as Exec} from 'child_process'; -import FileSystem from 'fs'; - -export class TraceBuilder { - /** - * @param {String} traceFile - */ - constructor(traceFile) { - this._traceFile = traceFile; - } - - /** - * @returns {String} - */ - get traceFile() { - return this._traceFile; - } - - /** - * @param {Function} callback - * @param {Boolean} cache - * @returns {TraceBuilder} - */ - compile(callback, cache = true) { - let cacheFile = `${this._traceFile}${TraceBuilder.CACHE_EXTENSION}`; - - if (!cache) { - this._compile(cacheFile, callback); - return this; - } - - FileSystem.exists(cacheFile, function(exists) { - if (exists) { - this._readFile(cacheFile, callback); - return; - } - - this._compile(cacheFile, callback); - }.bind(this)); - - return this; - } - - /** - * @param {String} filePath - * @param {Function} callback - * @private - */ - _readFile(filePath, callback) { - FileSystem.readFile(filePath, 'binary', callback); - } - - /** - * @param {String} outputFile - * @param {Function} callback - * @private - */ - _compile(outputFile, callback) { - Exec( - `${TraceBuilder.COMPILER} ${this._traceFile} --config=full --output=${outputFile}`, - function(error, stdout, stderr) { - if (error) { - callback(`Error while compiling profile: ${stderr}`, null); - return; - } - - this._readFile(outputFile, callback); - }.bind(this) - ); - } - - /** - * @returns {String} - */ - static get CACHE_EXTENSION() { - return '.html.cache'; - } - - /** - * @returns {String} - */ - static get COMPILER() { - return Path.join(__dirname, '../../tools/google_trace_viewer/tracing/trace2html'); - } -} diff --git a/src/lib/Terminal/Help.js b/src/lib/Terminal/Help.js index cdb7ae8c..e35491c5 100644 --- a/src/lib/Terminal/Help.js +++ b/src/lib/Terminal/Help.js @@ -113,12 +113,9 @@ export class Help { */ static _scoreSimilarWord(string, word, fuzziness = null) { // If the string is equal to the word, perfect match. - if (string === word) { + if (string === word || string.indexOf(word) === 0) { return 1; - } - - //if it's not a perfect match and is empty return 0 - if (!word) { + } else if (!word) { return 0; } diff --git a/src/lib/Terminal/Program.js b/src/lib/Terminal/Program.js index 795fff77..41092e59 100644 --- a/src/lib/Terminal/Program.js +++ b/src/lib/Terminal/Program.js @@ -160,6 +160,8 @@ export class Program { * @param {Array} args */ run(args = null) { + Program._logDriver.overrideJsConsole(false); + if (args || !this._inputParsed) { this.input(args); } @@ -171,6 +173,8 @@ export class Program { // @todo: add it for commands as well if (showAutoCompletion && showAutoCompletion.exists) { + Program._logDriver.overrideJsConsole(false, false); + this.help.printAutoCompletion( (this.hasCommands && command) ? command.value : '' ); @@ -183,7 +187,7 @@ export class Program { if (!subProgram) { console.log(''); - console.log(`No such command '${command.value}' found!`); + console.error(`No such command '${command.value}' found!`); this._outputListCommands(); this.exit(1); @@ -211,13 +215,12 @@ export class Program { this._validateInput(); try { - // @todo: find a better place for this - new DeepLog().overrideJsConsole(); + Program._logDriver.overrideJsConsole(); this._action.bind(this)(...this._args.listValues()); } catch (e) { - console.log(e.message); - console.log(e.stack); + console.error(e.message); + console.error(e.stack); this.exit(1); } @@ -435,4 +438,16 @@ export class Program { static get NODE_BINARY() { return 'node'; } + + /** + * @returns {DeepLog} + * @private + */ + static get _logDriver() { + if (!Program.hasOwnProperty('__deep_log')) { + Program.__deep_log = new DeepLog(); + } + + return Program.__deep_log; + } } diff --git a/src/package.json b/src/package.json index a323ed04..ea9aa9c1 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { "name": "deepify", - "version": "1.4.0", + "version": "1.5.0", "description": "DEEP Development Tools", "keywords": [ "Digital Enterprise End-To-End Platform", @@ -47,9 +47,8 @@ "url": "https://github.com/MitocGroup/deepify.git" }, "scripts": { - "coverage": "babel-node `which istanbul` cover --report lcovonly _mocha -- --ui tdd --recursive --reporter spec", "preinstall": "npm run compile", - "postinstall": "hooks/assure_deep_dev.js && hooks/autocomplete_deepify.sh", + "postinstall": "hooks/autocomplete_deepify.sh", "test": "babel-node `which isparta` cover --include 'lib/**/*.js' _mocha -- 'test/**/*.js' --reporter spec --ui tdd", "compile": "if [ -d 'lib/' ]; then BABEL_ENV=production babel lib/ --out-dir lib.compiled/; fi", "obfuscate-compiled": "if [ -d 'lib/' ]; then npm list -g --depth 0 uglify > /dev/null 2>&1 || npm install uglify -g; for f in $(find lib.compiled -type f -name *.js); do uglify -s ${f} -o ${f}; done; fi", @@ -61,17 +60,14 @@ "deep-db": "^1.x.x", "deep-core": "^1.x.x", "proxyquire": "^1.5.x", - "v8-profiler": "^5.3.x", - "traceviewify": "^0.4.x", "open": "^0.0.x", - "aws-sdk": "^2.2.x", "jsonfile": "^1.1.x", "fs-extra": "^0.23.x", - "sync-exec": "^0.6.x", "tmp": "^0.0.x", "aws-api-gw-client": "^0.1.x", "mime": "^1.3.x", - "gather-dependencies": "^1.0.x" + "gather-dependencies": "^1.0.x", + "aws-sdk": "^2.2.x" }, "devDependencies": { "chai": "^3.2.x", @@ -79,8 +75,8 @@ "sinon-chai": "^2.8.x" }, "engines": { - "node": ">=0.12 <5.0.0", - "npm": ">=2.10" + "node": ">=0.12 <5.0", + "npm": ">=2.10 <3.0" }, "os": [ "!win32" diff --git a/src/test/Lambda/Profile/AbstractProfiler.js b/src/test/Lambda/Profile/AbstractProfiler.js deleted file mode 100644 index 2eb7f4f1..00000000 --- a/src/test/Lambda/Profile/AbstractProfiler.js +++ /dev/null @@ -1,13 +0,0 @@ -// THIS TEST WAS GENERATED AUTOMATICALLY ON Mon Sep 14 2015 16:15:41 GMT+0300 (EEST) - -'use strict'; - -import chai from 'chai'; -import {AbstractProfiler} from '../../../lib/Lambda/Profile/AbstractProfiler'; - -// @todo: Add more advanced tests -suite('Lambda/Profile/AbstractProfiler', function() { - test('Class AbstractProfiler exists in Lambda/Profile/AbstractProfiler', function() { - chai.expect(typeof AbstractProfiler).to.equal('function'); - }); -}); diff --git a/src/test/Lambda/Profile/Profiler.js b/src/test/Lambda/Profile/Profiler.js deleted file mode 100644 index 28d10d6b..00000000 --- a/src/test/Lambda/Profile/Profiler.js +++ /dev/null @@ -1,13 +0,0 @@ -// THIS TEST WAS GENERATED AUTOMATICALLY ON Mon Sep 14 2015 16:15:41 GMT+0300 (EEST) - -'use strict'; - -import chai from 'chai'; -import {Profiler} from '../../../lib/Lambda/Profile/Profiler'; - -// @todo: Add more advanced tests -suite('Lambda/Profile/Profiler', function() { - test('Class Profiler exists in Lambda/Profile/Profiler', function() { - chai.expect(typeof Profiler).to.equal('function'); - }); -}); diff --git a/src/test/Lambda/Profile/StaticDumpFileProfiler.js b/src/test/Lambda/Profile/StaticDumpFileProfiler.js deleted file mode 100644 index f4486a53..00000000 --- a/src/test/Lambda/Profile/StaticDumpFileProfiler.js +++ /dev/null @@ -1,13 +0,0 @@ -// THIS TEST WAS GENERATED AUTOMATICALLY ON Mon Sep 14 2015 16:15:41 GMT+0300 (EEST) - -'use strict'; - -import chai from 'chai'; -import {StaticDumpFileProfiler} from '../../../lib/Lambda/Profile/StaticDumpFileProfiler'; - -// @todo: Add more advanced tests -suite('Lambda/Profile/StaticDumpFileProfiler', function() { - test('Class StaticDumpFileProfiler exists in Lambda/Profile/StaticDumpFileProfiler', function() { - chai.expect(typeof StaticDumpFileProfiler).to.equal('function'); - }); -}); diff --git a/src/test/Server/TraceBuilder.js b/src/test/Server/TraceBuilder.js deleted file mode 100644 index 6625c2f3..00000000 --- a/src/test/Server/TraceBuilder.js +++ /dev/null @@ -1,13 +0,0 @@ -// THIS TEST WAS GENERATED AUTOMATICALLY ON Mon Sep 14 2015 16:15:41 GMT+0300 (EEST) - -'use strict'; - -import chai from 'chai'; -import {TraceBuilder} from '../../lib/Server/TraceBuilder'; - -// @todo: Add more advanced tests -suite('Server/TraceBuilder', function() { - test('Class TraceBuilder exists in Server/TraceBuilder', function() { - chai.expect(typeof TraceBuilder).to.equal('function'); - }); -}); diff --git a/src/tools/google_trace_viewer/build/__init__.py b/src/tools/google_trace_viewer/build/__init__.py deleted file mode 100755 index 6464f9db..00000000 --- a/src/tools/google_trace_viewer/build/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os \ No newline at end of file diff --git a/src/tools/google_trace_viewer/build/checklicenses.py b/src/tools/google_trace_viewer/build/checklicenses.py deleted file mode 100755 index 8fbb9e4a..00000000 --- a/src/tools/google_trace_viewer/build/checklicenses.py +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -'''Makes sure that all files contain proper licensing information.''' - - -import json -import optparse -import os.path -import subprocess -import sys - -import logging - -def PrintUsage(): - print '''Usage: python checklicenses.py [--root ] [tocheck] - --root Specifies the repository root. This defaults to '../..' relative - to the script file. This will be correct given the normal location - of the script in '/tools/checklicenses'. - - tocheck Specifies the directory, relative to root, to check. This defaults - to '.' so it checks everything. - -Examples: - python checklicenses.py - python checklicenses.py --root ~/chromium/src third_party''' - - -WHITELISTED_LICENSES = [ - 'Apache (v2.0)', - 'BSD (3 clause)', - 'BSD-like', - 'MIT/X11 (BSD like)', - 'zlib/libpng', -] - - -PATH_SPECIFIC_WHITELISTED_LICENSES = { - 'tracing/third_party/devscripts': [ - 'GPL (v2 or later)', - ], -} - - -def check_licenses(base_directory, target_directory=None): - # Figure out which directory we have to check. - if not target_directory: - # No directory to check specified, use the repository root. - start_dir = base_directory - else: - # Directory specified. Start here. It's supposed to be relative to the - # base directory. - start_dir = os.path.abspath(os.path.join(base_directory, target_directory)) - - logging.info('Using base directory: %s' % base_directory) - logging.info('Checking: %s' % start_dir) - logging.info('') - - licensecheck_path = os.path.abspath(os.path.join(base_directory, - 'tracing', - 'third_party', - 'devscripts', - 'licensecheck.pl')) - - licensecheck = subprocess.Popen([licensecheck_path, - '-l', '100', - '-r', start_dir], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = licensecheck.communicate() - logging.info('----------- licensecheck stdout -----------') - logging.info(stdout) - logging.info('--------- end licensecheck stdout ---------') - if licensecheck.returncode != 0 or stderr: - print '----------- licensecheck stderr -----------' - print stderr - print '--------- end licensecheck stderr ---------' - return 1 - - used_suppressions = set() - errors = [] - - for line in stdout.splitlines(): - filename, license = line.split(':', 1) - filename = os.path.relpath(filename.strip(), base_directory) - - # All files in the build output directory are generated one way or another. - # There's no need to check them. - if filename.startswith('out/'): - continue - - # For now we're just interested in the license. - license = license.replace('*No copyright*', '').strip() - - # Skip generated files. - if 'GENERATED FILE' in license: - continue - - if license in WHITELISTED_LICENSES: - continue - - matched_prefixes = [ - prefix for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES - if filename.startswith(prefix) and - license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]] - if matched_prefixes: - used_suppressions.update(set(matched_prefixes)) - continue - - errors.append({'filename': filename, 'license': license}) - - if errors: - for error in errors: - print "'%s' has non-whitelisted license '%s'" % ( - error['filename'], error['license']) - print '\nFAILED\n' - print 'Please read', - print 'http://www.chromium.org/developers/adding-3rd-party-libraries' - print 'for more info how to handle the failure.' - print - print 'Please respect OWNERS of checklicenses.py. Changes violating' - print 'this requirement may be reverted.' - - # Do not print unused suppressions so that above message is clearly - # visible and gets proper attention. Too much unrelated output - # would be distracting and make the important points easier to miss. - - return 1 - - - return 0 - - -def main(): - default_root = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..')) - option_parser = optparse.OptionParser() - option_parser.add_option('--root', default=default_root, - dest='base_directory', - help='Specifies the repository root. This defaults ' - "to '..' relative to the script file, which " - 'will normally be the repository root.') - options, args = option_parser.parse_args() - - target_directory = None - if len(args) == 1: - target_directory = args[0] - elif len(args) > 1: - PrintUsage() - return 1 - results = check_licenses(options.base_directory, target_directory) - if not results: - print 'SUCCESS' - return results - - -if '__main__' == __name__: - sys.exit(main()) diff --git a/src/tools/google_trace_viewer/build/presubmit_checks.py b/src/tools/google_trace_viewer/build/presubmit_checks.py deleted file mode 100755 index 6469b717..00000000 --- a/src/tools/google_trace_viewer/build/presubmit_checks.py +++ /dev/null @@ -1,215 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os -import re -import sys -import time - -import checklicenses - -def _FormatError(msg, files): - return ('%s in these files:\n' % msg + - '\n'.join([' ' + x for x in files]) - ) - -def _ReportErrorFileAndLine(filename, line_num, dummy_line): - """Default error formatter for _FindNewViolationsOfRule.""" - return '%s:%s' % (filename, line_num) - -def _FindNewViolationsOfRule(callable_rule, input_api, - error_formatter=_ReportErrorFileAndLine): - """Find all newly introduced violations of a per-line rule (a callable). - - Arguments: - callable_rule: a callable taking a file extension and line of input and - returning True if the rule is satisfied and False if there was a problem. - input_api: object to enumerate the affected files. - source_file_filter: a filter to be passed to the input api. - error_formatter: a callable taking (filename, line_number, line) and - returning a formatted error string. - - Returns: - A list of the newly-introduced violations reported by the rule. - """ - errors = [] - for f in input_api.AffectedFiles(include_deletes=False): - # For speed, we do two passes, checking first the full file. Shelling out - # to the SCM to determine the changed region can be quite expensive on - # Win32. Assuming that most files will be kept problem-free, we can - # skip the SCM operations most of the time. - extension = str(f.filename).rsplit('.', 1)[-1] - if all(callable_rule(extension, line) for line in f.contents_as_lines): - continue # No violation found in full text: can skip considering diff. - - if input_api.IsIgnoredFile(f): - continue - - for line_num, line in f.changed_lines: - if not callable_rule(extension, line): - errors.append(error_formatter(f.filename, line_num, line)) - - return errors - -def CheckCopyright(input_api): - results = [] - results += _CheckCopyrightThirdParty(input_api) - results += _CheckCopyrightNonThirdParty(input_api) - return results - -def _CheckCopyrightThirdParty(input_api): - results = [] - has_third_party_change = any( - input_api.IsThirdParty(f) - for f in input_api.AffectedFiles(include_deletes=False)) - if has_third_party_change: - tracing_root = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..')) - tracing_third_party = os.path.join(tracing_root, 'tracing', 'third_party') - has_invalid_license = checklicenses.check_licenses( - tracing_root, tracing_third_party) - if has_invalid_license: - results.append( - 'License check encountered invalid licenses in tracing/third_party/.') - return results - -def _CheckCopyrightNonThirdParty(input_api): - project_name = 'Chromium' - - current_year = int(time.strftime('%Y')) - allow_old_years=True - if allow_old_years: - allowed_years = (str(s) for s in reversed(xrange(2006, current_year + 1))) - else: - allowed_years = [str(current_year)] - years_re = '(' + '|'.join(allowed_years) + ')' - - # The (c) is deprecated, but tolerate it until it's removed from all files. - non_html_license_header = ( - r'.*? Copyright (\(c\) )?%(year)s The %(project)s Authors\. ' - r'All rights reserved\.\n' - r'.*? Use of this source code is governed by a BSD-style license that ' - r'can be\n' - r'.*? found in the LICENSE file\.(?: \*/)?\n' - ) % { - 'year': years_re, - 'project': project_name, - } - non_html_license_re = re.compile(non_html_license_header, re.MULTILINE) - - html_license_header = ( - r'^Copyright (\(c\) )?%(year)s The %(project)s Authors\. ' - r'All rights reserved\.\n' - r'Use of this source code is governed by a BSD-style license that ' - r'can be\n' - r'found in the LICENSE file\.(?: \*/)?\n' - ) % { - 'year': years_re, - 'project': project_name, - } - html_license_re = re.compile(html_license_header, re.MULTILINE) - - sources = list(s for s in input_api.AffectedFiles(include_deletes=False) - if not input_api.IsThirdParty(s)) - - html_sources = [f for f in sources - if os.path.splitext(f.filename)[1] == '.html'] - non_html_sources = [f for f in sources - if os.path.splitext(f.filename)[1] != '.html'] - - results = [] - results += _Check(input_api, html_license_re, html_sources) - results += _Check(input_api, non_html_license_re, non_html_sources) - return results - -def _Check(input_api, license_re, sources): - bad_files = [] - for f in sources: - if input_api.IsIgnoredFile(f): - continue - contents = f.contents - if not license_re.search(contents): - bad_files.append(f.filename) - if bad_files: - return [_FormatError( - 'License must match:\n%s\n' % license_re.pattern + - 'Found a bad license header', - bad_files)] - return [] - -def CheckLongLines(input_api, maxlen=80): - """Checks that there aren't any lines longer than maxlen characters in any of - the text files to be submitted. - """ - maxlens = { - '': maxlen, - } - - # Language specific exceptions to max line length. - # '.h' is considered an obj-c file extension, since OBJC_EXCEPTIONS are a - # superset of CPP_EXCEPTIONS. - CPP_FILE_EXTS = ('c', 'cc') - CPP_EXCEPTIONS = ('#define', '#endif', '#if', '#include', '#pragma') - JAVA_FILE_EXTS = ('java',) - JAVA_EXCEPTIONS = ('import ', 'package ') - OBJC_FILE_EXTS = ('h', 'm', 'mm') - OBJC_EXCEPTIONS = ('#define', '#endif', '#if', '#import', '#include', - '#pragma') - - LANGUAGE_EXCEPTIONS = [ - (CPP_FILE_EXTS, CPP_EXCEPTIONS), - (JAVA_FILE_EXTS, JAVA_EXCEPTIONS), - (OBJC_FILE_EXTS, OBJC_EXCEPTIONS), - ] - - def no_long_lines(file_extension, line): - # Check for language specific exceptions. - if any(file_extension in exts and line.startswith(exceptions) - for exts, exceptions in LANGUAGE_EXCEPTIONS): - return True - - file_maxlen = maxlens.get(file_extension, maxlens['']) - # Stupidly long symbols that needs to be worked around if takes 66% of line. - long_symbol = file_maxlen * 2 / 3 - # Hard line length limit at 50% more. - extra_maxlen = file_maxlen * 3 / 2 - - line_len = len(line) - if line_len <= file_maxlen: - return True - - if '@suppress longLineCheck' in line: - return True - - if line_len > extra_maxlen: - return False - - if any((url in line) for url in ('file://', 'http://', 'https://')): - return True - - if 'url(' in line and file_extension == 'css': - return True - - if ', , @@$ - """ - return self._depot_tools_affected_file.ChangedContents() - - -class TvInputAPI(object): - """Thin wrapper around InputAPI class from depot_tools. - - See tools/depot_tools/presubmit_support.py in the Chromium tree. - """ - # TODO(petrcermak): Get rid of this class and use the wrapped object directly - # (https://github.com/google/trace-viewer/issues/932). - def __init__(self, depot_tools_input_api): - self._depot_tools_input_api = depot_tools_input_api - - def AffectedFiles(self, *args, **kwargs): - return map(_AffectedFile, - self._depot_tools_input_api.AffectedFiles(*args, **kwargs)) - - def IsIgnoredFile(self, affected_file): - if affected_file.filename.endswith('.png'): - return True - - if affected_file.filename.endswith('.svg'): - return True - - if affected_file.filename.endswith('.skp'): - return True - - if (affected_file.filename.endswith('.gypi') or - affected_file.filename.endswith('.gyp') or - affected_file.filename.endswith('.gn')): - return True - - if self.IsThirdParty(affected_file): - return True - - # Is test data? - test_data_path = tracing_project.TracingProject.test_data_path - if affected_file.absolute_path.startswith(test_data_path): - return True - - if (affected_file.filename.startswith('.gitignore') or - affected_file.filename.startswith('codereview.settings') or - affected_file.filename.startswith('tracing/.allow-devtools-save') or - affected_file.filename.startswith('tracing/AUTHORS') or - affected_file.filename.startswith('tracing/LICENSE') or - affected_file.filename.startswith('tracing/OWNERS') or - affected_file.filename.startswith('tracing/bower.json') or - affected_file.filename.startswith('tracing/.gitignore') or - affected_file.filename.startswith('tracing/.bowerrc') or - affected_file.filename.startswith('tracing/README.md') or - affected_file.filename.startswith( - 'tracing/examples/string_convert.js')): - return True - - return False - - def IsThirdParty(self, affected_file): - return affected_file.filename.startswith('tracing/third_party') diff --git a/src/tools/google_trace_viewer/hooks/__init__.py b/src/tools/google_trace_viewer/hooks/__init__.py deleted file mode 100755 index 3ee068de..00000000 --- a/src/tools/google_trace_viewer/hooks/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os -import sys diff --git a/src/tools/google_trace_viewer/hooks/install.py b/src/tools/google_trace_viewer/hooks/install.py deleted file mode 100755 index aa41f3d3..00000000 --- a/src/tools/google_trace_viewer/hooks/install.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import sys -import os - -_TOP_PATH = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..')) - -class Link(object): - def __init__(self, dst_path, src_path): - self.dst_path = dst_path - self.src_path = src_path - - def Update(self): - full_src_path = os.path.join(_TOP_PATH, self.src_path) - full_dst_path = os.path.join(_TOP_PATH, self.dst_path) - - full_dst_path_dirname = os.path.dirname(full_dst_path) - - src_path_rel = os.path.relpath(full_src_path, full_dst_path_dirname) - - assert os.path.exists(full_src_path) - if not os.path.exists(full_dst_path_dirname): - sys.stdout.write('ERROR\n\n') - sys.stdout.write(' dst dir doesn\'t exist\n' % self.full_dst_path_dirname) - sys.stdout.write('\n\n') - sys.exit(255) - - if os.path.exists(full_dst_path) or os.path.islink(full_dst_path): - if not os.path.islink(full_dst_path): - sys.stdout.write('ERROR\n\n') - sys.stdout.write(' Cannot install %s, dst already exists:\n %s\n' % ( - os.path.basename(self.src_path), full_dst_path)) - sys.stdout.write('\n\n') - sys.exit(255) - - existing_src_path_rel = os.readlink(full_dst_path) - if existing_src_path_rel == src_path_rel: - return - else: - sys.stdout.write('ERROR\n\n') - sys.stdout.write(' Cannot install %s, because %s is linked elsewhere.\n' % ( - os.path.basename(self.src_path), - os.path.relpath(full_dst_path))) - sys.stdout.write('\n\n') - sys.exit(255) - - os.symlink(src_path_rel, full_dst_path) - -def InstallHooks(): - if sys.platform == 'win32': - return - - # Remove old pre-commit, see https://github.com/google/trace-viewer/issues/932 - old_precommit = os.path.join(_TOP_PATH, '.git', 'hooks', 'pre-commit') - old_precommit_target = os.path.join(_TOP_PATH, 'hooks', 'pre_commit') - if (os.path.islink(old_precommit) and - os.path.abspath(os.readlink(old_precommit)) == old_precommit_target): - os.remove(old_precommit) - - links = [] - links.append(Link(os.path.join('.git', 'hooks', 'pre-push'), - os.path.join('hooks/pre_push'))) - - for l in links: - l.Update() diff --git a/src/tools/google_trace_viewer/hooks/pre_push b/src/tools/google_trace_viewer/hooks/pre_push deleted file mode 100755 index 7e7a2961..00000000 --- a/src/tools/google_trace_viewer/hooks/pre_push +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys -import subprocess - -"""Detect forced pushes (on the client) and prompt the user before going on.""" - -def read_from_tty(): - try: - import posix # No way to do this on Windows, just give up there. - with open('/dev/tty') as tty_fd: - return tty_fd.readline().strip() - except: - return None - - -def Main(): - # Allow force pushes in repos forked elsewhere (e.g. googlesource). - remote_url = sys.argv[2] if len(sys.argv) >= 2 else '' - if 'github.com' not in remote_url: - return 0 - - parts = sys.stdin.readline().split() - if len(parts) < 4: - return 0 - local_ref, local_sha, remote_ref, remote_sha = parts - cmd = ['git', 'rev-list', '--count', remote_sha, '--not', local_sha, - '--max-count=1'] - - is_force_push = '0' - try: - is_force_push = subprocess.check_output(cmd).strip() - except(subprocess.CalledProcessError): - return 0 - - if is_force_push != '0': - sys.stderr.write('\033[31mWARNING: Force pushing will break the ' + - 'github.com -> googlesource.com mirroring.\033[0m\n' + - 'This is almost certainly a bad idea.\n') - - sys.stderr.write('Type y to continue: ') - if read_from_tty() != 'y': - return 1 - - return 0 - - -if __name__ == '__main__': - sys.exit(Main()) diff --git a/src/tools/google_trace_viewer/perf_insights/README.md b/src/tools/google_trace_viewer/perf_insights/README.md deleted file mode 100755 index 56ccaf1d..00000000 --- a/src/tools/google_trace_viewer/perf_insights/README.md +++ /dev/null @@ -1,7 +0,0 @@ - -This folder contains code for http://performance-insights.appspot.com/, -and related client scripts. This is our UI for bulk-processing of trace data in -order to understand performance issues in Chrome, at scale. \ No newline at end of file diff --git a/src/tools/google_trace_viewer/perf_insights/__init__.py b/src/tools/google_trace_viewer/perf_insights/__init__.py deleted file mode 100755 index 6464f9db..00000000 --- a/src/tools/google_trace_viewer/perf_insights/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os \ No newline at end of file diff --git a/src/tools/google_trace_viewer/perf_insights/app.yaml b/src/tools/google_trace_viewer/perf_insights/app.yaml deleted file mode 100755 index 061114e1..00000000 --- a/src/tools/google_trace_viewer/perf_insights/app.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -application: performance-insights - -version: 1 -api_version: 1 -runtime: python27 -threadsafe: true - -builtins: -- remote_api: on - -handlers: -- url: /upload - script: perf_insights.upload.app - secure: always diff --git a/src/tools/google_trace_viewer/perf_insights/bin/__init__.py b/src/tools/google_trace_viewer/perf_insights/bin/__init__.py deleted file mode 100755 index 6464f9db..00000000 --- a/src/tools/google_trace_viewer/perf_insights/bin/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os \ No newline at end of file diff --git a/src/tools/google_trace_viewer/perf_insights/bin/map_traces b/src/tools/google_trace_viewer/perf_insights/bin/map_traces deleted file mode 100755 index 355724d7..00000000 --- a/src/tools/google_trace_viewer/perf_insights/bin/map_traces +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - from perf_insights.bin import map_traces - sys.exit(map_traces.Main(sys.argv[1:])) diff --git a/src/tools/google_trace_viewer/perf_insights/bin/map_traces.py b/src/tools/google_trace_viewer/perf_insights/bin/map_traces.py deleted file mode 100755 index a0ea9e5b..00000000 --- a/src/tools/google_trace_viewer/perf_insights/bin/map_traces.py +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -def Main(args): - pass diff --git a/src/tools/google_trace_viewer/perf_insights/bin/wr b/src/tools/google_trace_viewer/perf_insights/bin/wr deleted file mode 100755 index e9c28cf1..00000000 --- a/src/tools/google_trace_viewer/perf_insights/bin/wr +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - from perf_insights.bin import wr - sys.exit(wr.Main(sys.argv[1:])) diff --git a/src/tools/google_trace_viewer/perf_insights/bin/wr.py b/src/tools/google_trace_viewer/perf_insights/bin/wr.py deleted file mode 100755 index a0ea9e5b..00000000 --- a/src/tools/google_trace_viewer/perf_insights/bin/wr.py +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -def Main(args): - pass diff --git a/src/tools/google_trace_viewer/perf_insights/index.yaml b/src/tools/google_trace_viewer/perf_insights/index.yaml deleted file mode 100755 index e96f2643..00000000 --- a/src/tools/google_trace_viewer/perf_insights/index.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -indexes: - -- kind: TraceInfo - properties: - - name: prod - - name: date - direction: desc - -- kind: TraceInfo - properties: - - name: ver - - name: date - direction: desc - -- kind: TraceInfo - properties: - - name: prod - - name: ver - - name: date - direction: desc diff --git a/src/tools/google_trace_viewer/perf_insights/perf_insights/__init__.py b/src/tools/google_trace_viewer/perf_insights/perf_insights/__init__.py deleted file mode 100755 index 6464f9db..00000000 --- a/src/tools/google_trace_viewer/perf_insights/perf_insights/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os \ No newline at end of file diff --git a/src/tools/google_trace_viewer/perf_insights/perf_insights/trace_info.py b/src/tools/google_trace_viewer/perf_insights/perf_insights/trace_info.py deleted file mode 100755 index 079836c8..00000000 --- a/src/tools/google_trace_viewer/perf_insights/perf_insights/trace_info.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -from google.appengine.ext import ndb - - -class TraceInfo(ndb.Model): - prod = ndb.StringProperty(indexed=True) - ver = ndb.StringProperty(indexed=True) - remote_addr = ndb.StringProperty(indexed=True) - date = ndb.DateTimeProperty(auto_now_add=True, indexed=True) diff --git a/src/tools/google_trace_viewer/perf_insights/perf_insights/upload.py b/src/tools/google_trace_viewer/perf_insights/perf_insights/upload.py deleted file mode 100755 index 29b21abb..00000000 --- a/src/tools/google_trace_viewer/perf_insights/perf_insights/upload.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys -import webapp2 -import uuid - -from perf_insights import trace_info - -sys.path.append('third_party') -import cloudstorage as gcs - -default_retry_params = gcs.RetryParams(initial_delay=0.2, - max_delay=5.0, - backoff_factor=2, - max_retry_period=15) -gcs.set_default_retry_params(default_retry_params) - - -class UploadPage(webapp2.RequestHandler): - - def get(self): - self.response.out.write(""" - - Performance Insights - Trace Uploader -
-
-
-

- """) - - def post(self): - trace_uuid = str(uuid.uuid4()) - bucket_name = ('/performance-insights/' + trace_uuid) - gcs_file = gcs.open(bucket_name, - 'w', - content_type='application/octet-stream', - options={}, - retry_params=default_retry_params) - gcs_file.write(self.request.get('trace')) - gcs_file.close() - - trace_object = trace_info.TraceInfo(id=trace_uuid) - trace_object.prod = self.request.get('prod') - trace_object.ver = self.request.get('product_version') - trace_object.remote_addr = os.environ["REMOTE_ADDR"] - trace_object.put() - -app = webapp2.WSGIApplication([('/upload', UploadPage)]) diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/COPYING b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/COPYING deleted file mode 100755 index b09cd785..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/COPYING +++ /dev/null @@ -1,201 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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 - - 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. diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/README.chromium b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/README.chromium deleted file mode 100755 index fe387323..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/README.chromium +++ /dev/null @@ -1,12 +0,0 @@ -Name: Google Cloud Storage Client Library -URL: https://github.com/GoogleCloudPlatform/appengine-gcs-client -License: Apache 2.0 - -Description: -The Google Cloud Storage client library is a client-side library that is not -dependent on any specific version of App Engine for production use. - -Modifications: - - -Full license is in the COPYING file. diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/__init__.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/__init__.py deleted file mode 100755 index 349a021a..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2014 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Client Library for Google Cloud Storage.""" - - - - -from .api_utils import RetryParams -from .api_utils import set_default_retry_params -from cloudstorage_api import * -from .common import CSFileStat -from .common import GCSFileStat -from .common import validate_bucket_name -from .common import validate_bucket_path -from .common import validate_file_path -from errors import * -from storage_api import * diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/api_utils.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/api_utils.py deleted file mode 100755 index 680ac6bc..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/api_utils.py +++ /dev/null @@ -1,353 +0,0 @@ -# Copyright 2013 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Util functions and classes for cloudstorage_api.""" - - - -__all__ = ['set_default_retry_params', - 'RetryParams', - ] - -import copy -import httplib -import logging -import math -import os -import threading -import time -import urllib - - -try: - from google.appengine.api import app_identity - from google.appengine.api import urlfetch - from google.appengine.datastore import datastore_rpc - from google.appengine.ext import ndb - from google.appengine.ext.ndb import eventloop - from google.appengine.ext.ndb import tasklets - from google.appengine.ext.ndb import utils - from google.appengine import runtime - from google.appengine.runtime import apiproxy_errors -except ImportError: - from google.appengine.api import app_identity - from google.appengine.api import urlfetch - from google.appengine.datastore import datastore_rpc - from google.appengine import runtime - from google.appengine.runtime import apiproxy_errors - from google.appengine.ext import ndb - from google.appengine.ext.ndb import eventloop - from google.appengine.ext.ndb import tasklets - from google.appengine.ext.ndb import utils - - -_RETRIABLE_EXCEPTIONS = (urlfetch.DownloadError, - apiproxy_errors.Error, - app_identity.InternalError, - app_identity.BackendDeadlineExceeded) - -_thread_local_settings = threading.local() -_thread_local_settings.default_retry_params = None - - -def set_default_retry_params(retry_params): - """Set a default RetryParams for current thread current request.""" - _thread_local_settings.default_retry_params = copy.copy(retry_params) - - -def _get_default_retry_params(): - """Get default RetryParams for current request and current thread. - - Returns: - A new instance of the default RetryParams. - """ - default = getattr(_thread_local_settings, 'default_retry_params', None) - if default is None or not default.belong_to_current_request(): - return RetryParams() - else: - return copy.copy(default) - - -def _quote_filename(filename): - """Quotes filename to use as a valid URI path. - - Args: - filename: user provided filename. /bucket/filename. - - Returns: - The filename properly quoted to use as URI's path component. - """ - return urllib.quote(filename) - - -def _unquote_filename(filename): - """Unquotes a valid URI path back to its filename. - - This is the opposite of _quote_filename. - - Args: - filename: a quoted filename. /bucket/some%20filename. - - Returns: - The filename unquoted. - """ - return urllib.unquote(filename) - - -def _should_retry(resp): - """Given a urlfetch response, decide whether to retry that request.""" - return (resp.status_code == httplib.REQUEST_TIMEOUT or - (resp.status_code >= 500 and - resp.status_code < 600)) - - -class _RetryWrapper(object): - """A wrapper that wraps retry logic around any tasklet.""" - - def __init__(self, - retry_params, - retriable_exceptions=_RETRIABLE_EXCEPTIONS, - should_retry=lambda r: False): - """Init. - - Args: - retry_params: an RetryParams instance. - retriable_exceptions: a list of exception classes that are retriable. - should_retry: a function that takes a result from the tasklet and returns - a boolean. True if the result should be retried. - """ - self.retry_params = retry_params - self.retriable_exceptions = retriable_exceptions - self.should_retry = should_retry - - @ndb.tasklet - def run(self, tasklet, **kwds): - """Run a tasklet with retry. - - The retry should be transparent to the caller: if no results - are successful, the exception or result from the last retry is returned - to the caller. - - Args: - tasklet: the tasklet to run. - **kwds: keywords arguments to run the tasklet. - - Raises: - The exception from running the tasklet. - - Returns: - The result from running the tasklet. - """ - start_time = time.time() - n = 1 - - while True: - e = None - result = None - got_result = False - - try: - result = yield tasklet(**kwds) - got_result = True - if not self.should_retry(result): - raise ndb.Return(result) - except runtime.DeadlineExceededError: - logging.debug( - 'Tasklet has exceeded request deadline after %s seconds total', - time.time() - start_time) - raise - except self.retriable_exceptions, e: - pass - - if n == 1: - logging.debug('Tasklet is %r', tasklet) - - delay = self.retry_params.delay(n, start_time) - - if delay <= 0: - logging.debug( - 'Tasklet failed after %s attempts and %s seconds in total', - n, time.time() - start_time) - if got_result: - raise ndb.Return(result) - elif e is not None: - raise e - else: - assert False, 'Should never reach here.' - - if got_result: - logging.debug( - 'Got result %r from tasklet.', result) - else: - logging.debug( - 'Got exception "%r" from tasklet.', e) - logging.debug('Retry in %s seconds.', delay) - n += 1 - yield tasklets.sleep(delay) - - -class RetryParams(object): - """Retry configuration parameters.""" - - _DEFAULT_USER_AGENT = 'App Engine Python GCS Client' - - @datastore_rpc._positional(1) - def __init__(self, - backoff_factor=2.0, - initial_delay=0.1, - max_delay=10.0, - min_retries=3, - max_retries=6, - max_retry_period=30.0, - urlfetch_timeout=None, - save_access_token=False, - _user_agent=None): - """Init. - - This object is unique per request per thread. - - Library will retry according to this setting when App Engine Server - can't call urlfetch, urlfetch timed out, or urlfetch got a 408 or - 500-600 response. - - Args: - backoff_factor: exponential backoff multiplier. - initial_delay: seconds to delay for the first retry. - max_delay: max seconds to delay for every retry. - min_retries: min number of times to retry. This value is automatically - capped by max_retries. - max_retries: max number of times to retry. Set this to 0 for no retry. - max_retry_period: max total seconds spent on retry. Retry stops when - this period passed AND min_retries has been attempted. - urlfetch_timeout: timeout for urlfetch in seconds. Could be None, - in which case the value will be chosen by urlfetch module. - save_access_token: persist access token to datastore to avoid - excessive usage of GetAccessToken API. Usually the token is cached - in process and in memcache. In some cases, memcache isn't very - reliable. - _user_agent: The user agent string that you want to use in your requests. - """ - self.backoff_factor = self._check('backoff_factor', backoff_factor) - self.initial_delay = self._check('initial_delay', initial_delay) - self.max_delay = self._check('max_delay', max_delay) - self.max_retry_period = self._check('max_retry_period', max_retry_period) - self.max_retries = self._check('max_retries', max_retries, True, int) - self.min_retries = self._check('min_retries', min_retries, True, int) - if self.min_retries > self.max_retries: - self.min_retries = self.max_retries - - self.urlfetch_timeout = None - if urlfetch_timeout is not None: - self.urlfetch_timeout = self._check('urlfetch_timeout', urlfetch_timeout) - self.save_access_token = self._check('save_access_token', save_access_token, - True, bool) - self._user_agent = _user_agent or self._DEFAULT_USER_AGENT - - self._request_id = os.getenv('REQUEST_LOG_ID') - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return False - return self.__dict__ == other.__dict__ - - def __ne__(self, other): - return not self.__eq__(other) - - @classmethod - def _check(cls, name, val, can_be_zero=False, val_type=float): - """Check init arguments. - - Args: - name: name of the argument. For logging purpose. - val: value. Value has to be non negative number. - can_be_zero: whether value can be zero. - val_type: Python type of the value. - - Returns: - The value. - - Raises: - ValueError: when invalid value is passed in. - TypeError: when invalid value type is passed in. - """ - valid_types = [val_type] - if val_type is float: - valid_types.append(int) - - if type(val) not in valid_types: - raise TypeError( - 'Expect type %s for parameter %s' % (val_type.__name__, name)) - if val < 0: - raise ValueError( - 'Value for parameter %s has to be greater than 0' % name) - if not can_be_zero and val == 0: - raise ValueError( - 'Value for parameter %s can not be 0' % name) - return val - - def belong_to_current_request(self): - return os.getenv('REQUEST_LOG_ID') == self._request_id - - def delay(self, n, start_time): - """Calculate delay before the next retry. - - Args: - n: the number of current attempt. The first attempt should be 1. - start_time: the time when retry started in unix time. - - Returns: - Number of seconds to wait before next retry. -1 if retry should give up. - """ - if (n > self.max_retries or - (n > self.min_retries and - time.time() - start_time > self.max_retry_period)): - return -1 - return min( - math.pow(self.backoff_factor, n-1) * self.initial_delay, - self.max_delay) - - -def _run_until_rpc(): - """Eagerly evaluate tasklets until it is blocking on some RPC. - - Usually ndb eventloop el isn't run until some code calls future.get_result(). - - When an async tasklet is called, the tasklet wrapper evaluates the tasklet - code into a generator, enqueues a callback _help_tasklet_along onto - the el.current queue, and returns a future. - - _help_tasklet_along, when called by the el, will - get one yielded value from the generator. If the value if another future, - set up a callback _on_future_complete to invoke _help_tasklet_along - when the dependent future fulfills. If the value if a RPC, set up a - callback _on_rpc_complete to invoke _help_tasklet_along when the RPC fulfills. - Thus _help_tasklet_along drills down - the chain of futures until some future is blocked by RPC. El runs - all callbacks and constantly check pending RPC status. - """ - el = eventloop.get_event_loop() - while el.current: - el.run0() - - -def _eager_tasklet(tasklet): - """Decorator to turn tasklet to run eagerly.""" - - @utils.wrapping(tasklet) - def eager_wrapper(*args, **kwds): - fut = tasklet(*args, **kwds) - _run_until_rpc() - return fut - - return eager_wrapper diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/cloudstorage_api.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/cloudstorage_api.py deleted file mode 100755 index ba8be862..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/cloudstorage_api.py +++ /dev/null @@ -1,451 +0,0 @@ -# Copyright 2012 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""File Interface for Google Cloud Storage.""" - - - -from __future__ import with_statement - - - -__all__ = ['delete', - 'listbucket', - 'open', - 'stat', - ] - -import logging -import StringIO -import urllib -import xml.etree.cElementTree as ET -from . import api_utils -from . import common -from . import errors -from . import storage_api - - - -def open(filename, - mode='r', - content_type=None, - options=None, - read_buffer_size=storage_api.ReadBuffer.DEFAULT_BUFFER_SIZE, - retry_params=None, - _account_id=None): - """Opens a Google Cloud Storage file and returns it as a File-like object. - - Args: - filename: A Google Cloud Storage filename of form '/bucket/filename'. - mode: 'r' for reading mode. 'w' for writing mode. - In reading mode, the file must exist. In writing mode, a file will - be created or be overrode. - content_type: The MIME type of the file. str. Only valid in writing mode. - options: A str->basestring dict to specify additional headers to pass to - GCS e.g. {'x-goog-acl': 'private', 'x-goog-meta-foo': 'foo'}. - Supported options are x-goog-acl, x-goog-meta-, cache-control, - content-disposition, and content-encoding. - Only valid in writing mode. - See https://developers.google.com/storage/docs/reference-headers - for details. - read_buffer_size: The buffer size for read. Read keeps a buffer - and prefetches another one. To minimize blocking for large files, - always read by buffer size. To minimize number of RPC requests for - small files, set a large buffer size. Max is 30MB. - retry_params: An instance of api_utils.RetryParams for subsequent calls - to GCS from this file handle. If None, the default one is used. - _account_id: Internal-use only. - - Returns: - A reading or writing buffer that supports File-like interface. Buffer - must be closed after operations are done. - - Raises: - errors.AuthorizationError: if authorization failed. - errors.NotFoundError: if an object that's expected to exist doesn't. - ValueError: invalid open mode or if content_type or options are specified - in reading mode. - """ - common.validate_file_path(filename) - api = storage_api._get_storage_api(retry_params=retry_params, - account_id=_account_id) - filename = api_utils._quote_filename(filename) - - if mode == 'w': - common.validate_options(options) - return storage_api.StreamingBuffer(api, filename, content_type, options) - elif mode == 'r': - if content_type or options: - raise ValueError('Options and content_type can only be specified ' - 'for writing mode.') - return storage_api.ReadBuffer(api, - filename, - buffer_size=read_buffer_size) - else: - raise ValueError('Invalid mode %s.' % mode) - - -def delete(filename, retry_params=None, _account_id=None): - """Delete a Google Cloud Storage file. - - Args: - filename: A Google Cloud Storage filename of form '/bucket/filename'. - retry_params: An api_utils.RetryParams for this call to GCS. If None, - the default one is used. - _account_id: Internal-use only. - - Raises: - errors.NotFoundError: if the file doesn't exist prior to deletion. - """ - api = storage_api._get_storage_api(retry_params=retry_params, - account_id=_account_id) - common.validate_file_path(filename) - filename = api_utils._quote_filename(filename) - status, resp_headers, content = api.delete_object(filename) - errors.check_status(status, [204], filename, resp_headers=resp_headers, - body=content) - - -def stat(filename, retry_params=None, _account_id=None): - """Get GCSFileStat of a Google Cloud storage file. - - Args: - filename: A Google Cloud Storage filename of form '/bucket/filename'. - retry_params: An api_utils.RetryParams for this call to GCS. If None, - the default one is used. - _account_id: Internal-use only. - - Returns: - a GCSFileStat object containing info about this file. - - Raises: - errors.AuthorizationError: if authorization failed. - errors.NotFoundError: if an object that's expected to exist doesn't. - """ - common.validate_file_path(filename) - api = storage_api._get_storage_api(retry_params=retry_params, - account_id=_account_id) - status, headers, content = api.head_object( - api_utils._quote_filename(filename)) - errors.check_status(status, [200], filename, resp_headers=headers, - body=content) - file_stat = common.GCSFileStat( - filename=filename, - st_size=common.get_stored_content_length(headers), - st_ctime=common.http_time_to_posix(headers.get('last-modified')), - etag=headers.get('etag'), - content_type=headers.get('content-type'), - metadata=common.get_metadata(headers)) - - return file_stat - - -def _copy2(src, dst, metadata=None, retry_params=None): - """Copy the file content from src to dst. - - Internal use only! - - Args: - src: /bucket/filename - dst: /bucket/filename - metadata: a dict of metadata for this copy. If None, old metadata is copied. - For example, {'x-goog-meta-foo': 'bar'}. - retry_params: An api_utils.RetryParams for this call to GCS. If None, - the default one is used. - - Raises: - errors.AuthorizationError: if authorization failed. - errors.NotFoundError: if an object that's expected to exist doesn't. - """ - common.validate_file_path(src) - common.validate_file_path(dst) - - if metadata is None: - metadata = {} - copy_meta = 'COPY' - else: - copy_meta = 'REPLACE' - metadata.update({'x-goog-copy-source': src, - 'x-goog-metadata-directive': copy_meta}) - - api = storage_api._get_storage_api(retry_params=retry_params) - status, resp_headers, content = api.put_object( - api_utils._quote_filename(dst), headers=metadata) - errors.check_status(status, [200], src, metadata, resp_headers, body=content) - - -def listbucket(path_prefix, marker=None, prefix=None, max_keys=None, - delimiter=None, retry_params=None, _account_id=None): - """Returns a GCSFileStat iterator over a bucket. - - Optional arguments can limit the result to a subset of files under bucket. - - This function has two modes: - 1. List bucket mode: Lists all files in the bucket without any concept of - hierarchy. GCS doesn't have real directory hierarchies. - 2. Directory emulation mode: If you specify the 'delimiter' argument, - it is used as a path separator to emulate a hierarchy of directories. - In this mode, the "path_prefix" argument should end in the delimiter - specified (thus designates a logical directory). The logical directory's - contents, both files and subdirectories, are listed. The names of - subdirectories returned will end with the delimiter. So listbucket - can be called with the subdirectory name to list the subdirectory's - contents. - - Args: - path_prefix: A Google Cloud Storage path of format "/bucket" or - "/bucket/prefix". Only objects whose fullpath starts with the - path_prefix will be returned. - marker: Another path prefix. Only objects whose fullpath starts - lexicographically after marker will be returned (exclusive). - prefix: Deprecated. Use path_prefix. - max_keys: The limit on the number of objects to return. int. - For best performance, specify max_keys only if you know how many objects - you want. Otherwise, this method requests large batches and handles - pagination for you. - delimiter: Use to turn on directory mode. str of one or multiple chars - that your bucket uses as its directory separator. - retry_params: An api_utils.RetryParams for this call to GCS. If None, - the default one is used. - _account_id: Internal-use only. - - Examples: - For files "/bucket/a", - "/bucket/bar/1" - "/bucket/foo", - "/bucket/foo/1", "/bucket/foo/2/1", "/bucket/foo/3/1", - - Regular mode: - listbucket("/bucket/f", marker="/bucket/foo/1") - will match "/bucket/foo/2/1", "/bucket/foo/3/1". - - Directory mode: - listbucket("/bucket/", delimiter="/") - will match "/bucket/a, "/bucket/bar/" "/bucket/foo", "/bucket/foo/". - listbucket("/bucket/foo/", delimiter="/") - will match "/bucket/foo/1", "/bucket/foo/2/", "/bucket/foo/3/" - - Returns: - Regular mode: - A GCSFileStat iterator over matched files ordered by filename. - The iterator returns GCSFileStat objects. filename, etag, st_size, - st_ctime, and is_dir are set. - - Directory emulation mode: - A GCSFileStat iterator over matched files and directories ordered by - name. The iterator returns GCSFileStat objects. For directories, - only the filename and is_dir fields are set. - - The last name yielded can be used as next call's marker. - """ - if prefix: - common.validate_bucket_path(path_prefix) - bucket = path_prefix - else: - bucket, prefix = common._process_path_prefix(path_prefix) - - if marker and marker.startswith(bucket): - marker = marker[len(bucket) + 1:] - - api = storage_api._get_storage_api(retry_params=retry_params, - account_id=_account_id) - options = {} - if marker: - options['marker'] = marker - if max_keys: - options['max-keys'] = max_keys - if prefix: - options['prefix'] = prefix - if delimiter: - options['delimiter'] = delimiter - - return _Bucket(api, bucket, options) - - -class _Bucket(object): - """A wrapper for a GCS bucket as the return value of listbucket.""" - - def __init__(self, api, path, options): - """Initialize. - - Args: - api: storage_api instance. - path: bucket path of form '/bucket'. - options: a dict of listbucket options. Please see listbucket doc. - """ - self._init(api, path, options) - - def _init(self, api, path, options): - self._api = api - self._path = path - self._options = options.copy() - self._get_bucket_fut = self._api.get_bucket_async( - self._path + '?' + urllib.urlencode(self._options)) - self._last_yield = None - self._new_max_keys = self._options.get('max-keys') - - def __getstate__(self): - options = self._options - if self._last_yield: - options['marker'] = self._last_yield.filename[len(self._path) + 1:] - if self._new_max_keys is not None: - options['max-keys'] = self._new_max_keys - return {'api': self._api, - 'path': self._path, - 'options': options} - - def __setstate__(self, state): - self._init(state['api'], state['path'], state['options']) - - def __iter__(self): - """Iter over the bucket. - - Yields: - GCSFileStat: a GCSFileStat for an object in the bucket. - They are ordered by GCSFileStat.filename. - """ - total = 0 - max_keys = self._options.get('max-keys') - - while self._get_bucket_fut: - status, resp_headers, content = self._get_bucket_fut.get_result() - errors.check_status(status, [200], self._path, resp_headers=resp_headers, - body=content, extras=self._options) - - if self._should_get_another_batch(content): - self._get_bucket_fut = self._api.get_bucket_async( - self._path + '?' + urllib.urlencode(self._options)) - else: - self._get_bucket_fut = None - - root = ET.fromstring(content) - dirs = self._next_dir_gen(root) - files = self._next_file_gen(root) - next_file = files.next() - next_dir = dirs.next() - - while ((max_keys is None or total < max_keys) and - not (next_file is None and next_dir is None)): - total += 1 - if next_file is None: - self._last_yield = next_dir - next_dir = dirs.next() - elif next_dir is None: - self._last_yield = next_file - next_file = files.next() - elif next_dir < next_file: - self._last_yield = next_dir - next_dir = dirs.next() - elif next_file < next_dir: - self._last_yield = next_file - next_file = files.next() - else: - logging.error( - 'Should never reach. next file is %r. next dir is %r.', - next_file, next_dir) - if self._new_max_keys: - self._new_max_keys -= 1 - yield self._last_yield - - def _next_file_gen(self, root): - """Generator for next file element in the document. - - Args: - root: root element of the XML tree. - - Yields: - GCSFileStat for the next file. - """ - for e in root.getiterator(common._T_CONTENTS): - st_ctime, size, etag, key = None, None, None, None - for child in e.getiterator('*'): - if child.tag == common._T_LAST_MODIFIED: - st_ctime = common.dt_str_to_posix(child.text) - elif child.tag == common._T_ETAG: - etag = child.text - elif child.tag == common._T_SIZE: - size = child.text - elif child.tag == common._T_KEY: - key = child.text - yield common.GCSFileStat(self._path + '/' + key, - size, etag, st_ctime) - e.clear() - yield None - - def _next_dir_gen(self, root): - """Generator for next directory element in the document. - - Args: - root: root element in the XML tree. - - Yields: - GCSFileStat for the next directory. - """ - for e in root.getiterator(common._T_COMMON_PREFIXES): - yield common.GCSFileStat( - self._path + '/' + e.find(common._T_PREFIX).text, - st_size=None, etag=None, st_ctime=None, is_dir=True) - e.clear() - yield None - - def _should_get_another_batch(self, content): - """Whether to issue another GET bucket call. - - Args: - content: response XML. - - Returns: - True if should, also update self._options for the next request. - False otherwise. - """ - if ('max-keys' in self._options and - self._options['max-keys'] <= common._MAX_GET_BUCKET_RESULT): - return False - - elements = self._find_elements( - content, set([common._T_IS_TRUNCATED, - common._T_NEXT_MARKER])) - if elements.get(common._T_IS_TRUNCATED, 'false').lower() != 'true': - return False - - next_marker = elements.get(common._T_NEXT_MARKER) - if next_marker is None: - self._options.pop('marker', None) - return False - self._options['marker'] = next_marker - return True - - def _find_elements(self, result, elements): - """Find interesting elements from XML. - - This function tries to only look for specified elements - without parsing the entire XML. The specified elements is better - located near the beginning. - - Args: - result: response XML. - elements: a set of interesting element tags. - - Returns: - A dict from element tag to element value. - """ - element_mapping = {} - result = StringIO.StringIO(result) - for _, e in ET.iterparse(result, events=('end',)): - if not elements: - break - if e.tag in elements: - element_mapping[e.tag] = e.text - elements.remove(e.tag) - return element_mapping diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/common.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/common.py deleted file mode 100755 index ab9c8df3..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/common.py +++ /dev/null @@ -1,429 +0,0 @@ -# Copyright 2012 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Helpers shared by cloudstorage_stub and cloudstorage_api.""" - - - - - -__all__ = ['CS_XML_NS', - 'CSFileStat', - 'dt_str_to_posix', - 'local_api_url', - 'LOCAL_GCS_ENDPOINT', - 'local_run', - 'get_access_token', - 'get_stored_content_length', - 'get_metadata', - 'GCSFileStat', - 'http_time_to_posix', - 'memory_usage', - 'posix_time_to_http', - 'posix_to_dt_str', - 'set_access_token', - 'validate_options', - 'validate_bucket_name', - 'validate_bucket_path', - 'validate_file_path', - ] - - -import calendar -import datetime -from email import utils as email_utils -import logging -import os -import re - -try: - from google.appengine.api import runtime -except ImportError: - from google.appengine.api import runtime - - -_GCS_BUCKET_REGEX_BASE = r'[a-z0-9\.\-_]{3,63}' -_GCS_BUCKET_REGEX = re.compile(_GCS_BUCKET_REGEX_BASE + r'$') -_GCS_BUCKET_PATH_REGEX = re.compile(r'/' + _GCS_BUCKET_REGEX_BASE + r'$') -_GCS_PATH_PREFIX_REGEX = re.compile(r'/' + _GCS_BUCKET_REGEX_BASE + r'.*') -_GCS_FULLPATH_REGEX = re.compile(r'/' + _GCS_BUCKET_REGEX_BASE + r'/.*') -_GCS_METADATA = ['x-goog-meta-', - 'content-disposition', - 'cache-control', - 'content-encoding'] -_GCS_OPTIONS = _GCS_METADATA + ['x-goog-acl'] -CS_XML_NS = 'http://doc.s3.amazonaws.com/2006-03-01' -LOCAL_GCS_ENDPOINT = '/_ah/gcs' -_access_token = '' - - -_MAX_GET_BUCKET_RESULT = 1000 - - -def set_access_token(access_token): - """Set the shared access token to authenticate with Google Cloud Storage. - - When set, the library will always attempt to communicate with the - real Google Cloud Storage with this token even when running on dev appserver. - Note the token could expire so it's up to you to renew it. - - When absent, the library will automatically request and refresh a token - on appserver, or when on dev appserver, talk to a Google Cloud Storage - stub. - - Args: - access_token: you can get one by run 'gsutil -d ls' and copy the - str after 'Bearer'. - """ - global _access_token - _access_token = access_token - - -def get_access_token(): - """Returns the shared access token.""" - return _access_token - - -class GCSFileStat(object): - """Container for GCS file stat.""" - - def __init__(self, - filename, - st_size, - etag, - st_ctime, - content_type=None, - metadata=None, - is_dir=False): - """Initialize. - - For files, the non optional arguments are always set. - For directories, only filename and is_dir is set. - - Args: - filename: a Google Cloud Storage filename of form '/bucket/filename'. - st_size: file size in bytes. long compatible. - etag: hex digest of the md5 hash of the file's content. str. - st_ctime: posix file creation time. float compatible. - content_type: content type. str. - metadata: a str->str dict of user specified options when creating - the file. Possible keys are x-goog-meta-, content-disposition, - content-encoding, and cache-control. - is_dir: True if this represents a directory. False if this is a real file. - """ - self.filename = filename - self.is_dir = is_dir - self.st_size = None - self.st_ctime = None - self.etag = None - self.content_type = content_type - self.metadata = metadata - - if not is_dir: - self.st_size = long(st_size) - self.st_ctime = float(st_ctime) - if etag[0] == '"' and etag[-1] == '"': - etag = etag[1:-1] - self.etag = etag - - def __repr__(self): - if self.is_dir: - return '(directory: %s)' % self.filename - - return ( - '(filename: %(filename)s, st_size: %(st_size)s, ' - 'st_ctime: %(st_ctime)s, etag: %(etag)s, ' - 'content_type: %(content_type)s, ' - 'metadata: %(metadata)s)' % - dict(filename=self.filename, - st_size=self.st_size, - st_ctime=self.st_ctime, - etag=self.etag, - content_type=self.content_type, - metadata=self.metadata)) - - def __cmp__(self, other): - if not isinstance(other, self.__class__): - raise ValueError('Argument to cmp must have the same type. ' - 'Expect %s, got %s', self.__class__.__name__, - other.__class__.__name__) - if self.filename > other.filename: - return 1 - elif self.filename < other.filename: - return -1 - return 0 - - def __hash__(self): - if self.etag: - return hash(self.etag) - return hash(self.filename) - - -CSFileStat = GCSFileStat - - -def get_stored_content_length(headers): - """Return the content length (in bytes) of the object as stored in GCS. - - x-goog-stored-content-length should always be present except when called via - the local dev_appserver. Therefore if it is not present we default to the - standard content-length header. - - Args: - headers: a dict of headers from the http response. - - Returns: - the stored content length. - """ - length = headers.get('x-goog-stored-content-length') - if length is None: - length = headers.get('content-length') - return length - - -def get_metadata(headers): - """Get user defined options from HTTP response headers.""" - return dict((k, v) for k, v in headers.iteritems() - if any(k.lower().startswith(valid) for valid in _GCS_METADATA)) - - -def validate_bucket_name(name): - """Validate a Google Storage bucket name. - - Args: - name: a Google Storage bucket name with no prefix or suffix. - - Raises: - ValueError: if name is invalid. - """ - _validate_path(name) - if not _GCS_BUCKET_REGEX.match(name): - raise ValueError('Bucket should be 3-63 characters long using only a-z,' - '0-9, underscore, dash or dot but got %s' % name) - - -def validate_bucket_path(path): - """Validate a Google Cloud Storage bucket path. - - Args: - path: a Google Storage bucket path. It should have form '/bucket'. - - Raises: - ValueError: if path is invalid. - """ - _validate_path(path) - if not _GCS_BUCKET_PATH_REGEX.match(path): - raise ValueError('Bucket should have format /bucket ' - 'but got %s' % path) - - -def validate_file_path(path): - """Validate a Google Cloud Storage file path. - - Args: - path: a Google Storage file path. It should have form '/bucket/filename'. - - Raises: - ValueError: if path is invalid. - """ - _validate_path(path) - if not _GCS_FULLPATH_REGEX.match(path): - raise ValueError('Path should have format /bucket/filename ' - 'but got %s' % path) - - -def _process_path_prefix(path_prefix): - """Validate and process a Google Cloud Stoarge path prefix. - - Args: - path_prefix: a Google Cloud Storage path prefix of format '/bucket/prefix' - or '/bucket/' or '/bucket'. - - Raises: - ValueError: if path is invalid. - - Returns: - a tuple of /bucket and prefix. prefix can be None. - """ - _validate_path(path_prefix) - if not _GCS_PATH_PREFIX_REGEX.match(path_prefix): - raise ValueError('Path prefix should have format /bucket, /bucket/, ' - 'or /bucket/prefix but got %s.' % path_prefix) - bucket_name_end = path_prefix.find('/', 1) - bucket = path_prefix - prefix = None - if bucket_name_end != -1: - bucket = path_prefix[:bucket_name_end] - prefix = path_prefix[bucket_name_end + 1:] or None - return bucket, prefix - - -def _validate_path(path): - """Basic validation of Google Storage paths. - - Args: - path: a Google Storage path. It should have form '/bucket/filename' - or '/bucket'. - - Raises: - ValueError: if path is invalid. - TypeError: if path is not of type basestring. - """ - if not path: - raise ValueError('Path is empty') - if not isinstance(path, basestring): - raise TypeError('Path should be a string but is %s (%s).' % - (path.__class__, path)) - - -def validate_options(options): - """Validate Google Cloud Storage options. - - Args: - options: a str->basestring dict of options to pass to Google Cloud Storage. - - Raises: - ValueError: if option is not supported. - TypeError: if option is not of type str or value of an option - is not of type basestring. - """ - if not options: - return - - for k, v in options.iteritems(): - if not isinstance(k, str): - raise TypeError('option %r should be a str.' % k) - if not any(k.lower().startswith(valid) for valid in _GCS_OPTIONS): - raise ValueError('option %s is not supported.' % k) - if not isinstance(v, basestring): - raise TypeError('value %r for option %s should be of type basestring.' % - (v, k)) - - -def http_time_to_posix(http_time): - """Convert HTTP time format to posix time. - - See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 - for http time format. - - Args: - http_time: time in RFC 2616 format. e.g. - "Mon, 20 Nov 1995 19:12:08 GMT". - - Returns: - A float of secs from unix epoch. - """ - if http_time is not None: - return email_utils.mktime_tz(email_utils.parsedate_tz(http_time)) - - -def posix_time_to_http(posix_time): - """Convert posix time to HTML header time format. - - Args: - posix_time: unix time. - - Returns: - A datatime str in RFC 2616 format. - """ - if posix_time: - return email_utils.formatdate(posix_time, usegmt=True) - - -_DT_FORMAT = '%Y-%m-%dT%H:%M:%S' - - -def dt_str_to_posix(dt_str): - """format str to posix. - - datetime str is of format %Y-%m-%dT%H:%M:%S.%fZ, - e.g. 2013-04-12T00:22:27.978Z. According to ISO 8601, T is a separator - between date and time when they are on the same line. - Z indicates UTC (zero meridian). - - A pointer: http://www.cl.cam.ac.uk/~mgk25/iso-time.html - - This is used to parse LastModified node from GCS's GET bucket XML response. - - Args: - dt_str: A datetime str. - - Returns: - A float of secs from unix epoch. By posix definition, epoch is midnight - 1970/1/1 UTC. - """ - parsable, _ = dt_str.split('.') - dt = datetime.datetime.strptime(parsable, _DT_FORMAT) - return calendar.timegm(dt.utctimetuple()) - - -def posix_to_dt_str(posix): - """Reverse of str_to_datetime. - - This is used by GCS stub to generate GET bucket XML response. - - Args: - posix: A float of secs from unix epoch. - - Returns: - A datetime str. - """ - dt = datetime.datetime.utcfromtimestamp(posix) - dt_str = dt.strftime(_DT_FORMAT) - return dt_str + '.000Z' - - -def local_run(): - """Whether we should hit GCS dev appserver stub.""" - server_software = os.environ.get('SERVER_SOFTWARE') - if server_software is None: - return True - if 'remote_api' in server_software: - return False - if server_software.startswith(('Development', 'testutil')): - return True - return False - - -def local_api_url(): - """Return URL for GCS emulation on dev appserver.""" - return 'http://%s%s' % (os.environ.get('HTTP_HOST'), LOCAL_GCS_ENDPOINT) - - -def memory_usage(method): - """Log memory usage before and after a method.""" - def wrapper(*args, **kwargs): - logging.info('Memory before method %s is %s.', - method.__name__, runtime.memory_usage().current()) - result = method(*args, **kwargs) - logging.info('Memory after method %s is %s', - method.__name__, runtime.memory_usage().current()) - return result - return wrapper - - -def _add_ns(tagname): - return '{%(ns)s}%(tag)s' % {'ns': CS_XML_NS, - 'tag': tagname} - - -_T_CONTENTS = _add_ns('Contents') -_T_LAST_MODIFIED = _add_ns('LastModified') -_T_ETAG = _add_ns('ETag') -_T_KEY = _add_ns('Key') -_T_SIZE = _add_ns('Size') -_T_PREFIX = _add_ns('Prefix') -_T_COMMON_PREFIXES = _add_ns('CommonPrefixes') -_T_NEXT_MARKER = _add_ns('NextMarker') -_T_IS_TRUNCATED = _add_ns('IsTruncated') diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/errors.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/errors.py deleted file mode 100755 index 21743806..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/errors.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2012 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Google Cloud Storage specific Files API calls.""" - - - - - -__all__ = ['AuthorizationError', - 'check_status', - 'Error', - 'FatalError', - 'FileClosedError', - 'ForbiddenError', - 'InvalidRange', - 'NotFoundError', - 'ServerError', - 'TimeoutError', - 'TransientError', - ] - -import httplib - - -class Error(Exception): - """Base error for all gcs operations. - - Error can happen on GAE side or GCS server side. - For details on a particular GCS HTTP response code, see - https://developers.google.com/storage/docs/reference-status#standardcodes - """ - - -class TransientError(Error): - """TransientError could be retried.""" - - -class TimeoutError(TransientError): - """HTTP 408 timeout.""" - - -class FatalError(Error): - """FatalError shouldn't be retried.""" - - -class FileClosedError(FatalError): - """File is already closed. - - This can happen when the upload has finished but 'write' is called on - a stale upload handle. - """ - - -class NotFoundError(FatalError): - """HTTP 404 resource not found.""" - - -class ForbiddenError(FatalError): - """HTTP 403 Forbidden. - - While GCS replies with a 403 error for many reasons, the most common one - is due to bucket permission not correctly setup for your app to access. - """ - - -class AuthorizationError(FatalError): - """HTTP 401 authentication required. - - Unauthorized request has been received by GCS. - - This error is mostly handled by GCS client. GCS client will request - a new access token and retry the request. - """ - - -class InvalidRange(FatalError): - """HTTP 416 RequestRangeNotSatifiable.""" - - -class ServerError(TransientError): - """HTTP >= 500 server side error.""" - - -def check_status(status, expected, path, headers=None, - resp_headers=None, body=None, extras=None): - """Check HTTP response status is expected. - - Args: - status: HTTP response status. int. - expected: a list of expected statuses. A list of ints. - path: filename or a path prefix. - headers: HTTP request headers. - resp_headers: HTTP response headers. - body: HTTP response body. - extras: extra info to be logged verbatim if error occurs. - - Raises: - AuthorizationError: if authorization failed. - NotFoundError: if an object that's expected to exist doesn't. - TimeoutError: if HTTP request timed out. - ServerError: if server experienced some errors. - FatalError: if any other unexpected errors occurred. - """ - if status in expected: - return - - msg = ('Expect status %r from Google Storage. But got status %d.\n' - 'Path: %r.\n' - 'Request headers: %r.\n' - 'Response headers: %r.\n' - 'Body: %r.\n' - 'Extra info: %r.\n' % - (expected, status, path, headers, resp_headers, body, extras)) - - if status == httplib.UNAUTHORIZED: - raise AuthorizationError(msg) - elif status == httplib.FORBIDDEN: - raise ForbiddenError(msg) - elif status == httplib.NOT_FOUND: - raise NotFoundError(msg) - elif status == httplib.REQUEST_TIMEOUT: - raise TimeoutError(msg) - elif status == httplib.REQUESTED_RANGE_NOT_SATISFIABLE: - raise InvalidRange(msg) - elif (status == httplib.OK and 308 in expected and - httplib.OK not in expected): - raise FileClosedError(msg) - elif status >= 500: - raise ServerError(msg) - else: - raise FatalError(msg) diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/rest_api.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/rest_api.py deleted file mode 100755 index 437c09d7..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/rest_api.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright 2012 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Base and helper classes for Google RESTful APIs.""" - - - - - -__all__ = ['add_sync_methods'] - -import random -import time - -from . import api_utils - -try: - from google.appengine.api import app_identity - from google.appengine.ext import ndb -except ImportError: - from google.appengine.api import app_identity - from google.appengine.ext import ndb - - - -def _make_sync_method(name): - """Helper to synthesize a synchronous method from an async method name. - - Used by the @add_sync_methods class decorator below. - - Args: - name: The name of the synchronous method. - - Returns: - A method (with first argument 'self') that retrieves and calls - self., passing its own arguments, expects it to return a - Future, and then waits for and returns that Future's result. - """ - - def sync_wrapper(self, *args, **kwds): - method = getattr(self, name) - future = method(*args, **kwds) - return future.get_result() - - return sync_wrapper - - -def add_sync_methods(cls): - """Class decorator to add synchronous methods corresponding to async methods. - - This modifies the class in place, adding additional methods to it. - If a synchronous method of a given name already exists it is not - replaced. - - Args: - cls: A class. - - Returns: - The same class, modified in place. - """ - for name in cls.__dict__.keys(): - if name.endswith('_async'): - sync_name = name[:-6] - if not hasattr(cls, sync_name): - setattr(cls, sync_name, _make_sync_method(name)) - return cls - - -class _AE_TokenStorage_(ndb.Model): - """Entity to store app_identity tokens in memcache.""" - - token = ndb.StringProperty() - expires = ndb.FloatProperty() - - -@ndb.tasklet -def _make_token_async(scopes, service_account_id): - """Get a fresh authentication token. - - Args: - scopes: A list of scopes. - service_account_id: Internal-use only. - - Raises: - An ndb.Return with a tuple (token, expiration_time) where expiration_time is - seconds since the epoch. - """ - rpc = app_identity.create_rpc() - app_identity.make_get_access_token_call(rpc, scopes, service_account_id) - token, expires_at = yield rpc - raise ndb.Return((token, expires_at)) - - -class _RestApi(object): - """Base class for REST-based API wrapper classes. - - This class manages authentication tokens and request retries. All - APIs are available as synchronous and async methods; synchronous - methods are synthesized from async ones by the add_sync_methods() - function in this module. - - WARNING: Do NOT directly use this api. It's an implementation detail - and is subject to change at any release. - """ - - def __init__(self, scopes, service_account_id=None, token_maker=None, - retry_params=None): - """Constructor. - - Args: - scopes: A scope or a list of scopes. - service_account_id: Internal use only. - token_maker: An asynchronous function of the form - (scopes, service_account_id) -> (token, expires). - retry_params: An instance of api_utils.RetryParams. If None, the - default for current thread will be used. - """ - - if isinstance(scopes, basestring): - scopes = [scopes] - self.scopes = scopes - self.service_account_id = service_account_id - self.make_token_async = token_maker or _make_token_async - if not retry_params: - retry_params = api_utils._get_default_retry_params() - self.retry_params = retry_params - self.user_agent = {'User-Agent': retry_params._user_agent} - self.expiration_headroom = random.randint(60, 240) - - def __getstate__(self): - """Store state as part of serialization/pickling.""" - return {'scopes': self.scopes, - 'id': self.service_account_id, - 'a_maker': (None if self.make_token_async == _make_token_async - else self.make_token_async), - 'retry_params': self.retry_params, - 'expiration_headroom': self.expiration_headroom} - - def __setstate__(self, state): - """Restore state as part of deserialization/unpickling.""" - self.__init__(state['scopes'], - service_account_id=state['id'], - token_maker=state['a_maker'], - retry_params=state['retry_params']) - self.expiration_headroom = state['expiration_headroom'] - - @ndb.tasklet - def do_request_async(self, url, method='GET', headers=None, payload=None, - deadline=None, callback=None): - """Issue one HTTP request. - - It performs async retries using tasklets. - - Args: - url: the url to fetch. - method: the method in which to fetch. - headers: the http headers. - payload: the data to submit in the fetch. - deadline: the deadline in which to make the call. - callback: the call to make once completed. - - Yields: - The async fetch of the url. - """ - retry_wrapper = api_utils._RetryWrapper( - self.retry_params, - retriable_exceptions=api_utils._RETRIABLE_EXCEPTIONS, - should_retry=api_utils._should_retry) - resp = yield retry_wrapper.run( - self.urlfetch_async, - url=url, - method=method, - headers=headers, - payload=payload, - deadline=deadline, - callback=callback, - follow_redirects=False) - raise ndb.Return((resp.status_code, resp.headers, resp.content)) - - @ndb.tasklet - def get_token_async(self, refresh=False): - """Get an authentication token. - - The token is cached in memcache, keyed by the scopes argument. - Uses a random token expiration headroom value generated in the constructor - to eliminate a burst of GET_ACCESS_TOKEN API requests. - - Args: - refresh: If True, ignore a cached token; default False. - - Yields: - An authentication token. This token is guaranteed to be non-expired. - """ - key = '%s,%s' % (self.service_account_id, ','.join(self.scopes)) - ts = yield _AE_TokenStorage_.get_by_id_async( - key, use_cache=True, use_memcache=True, - use_datastore=self.retry_params.save_access_token) - if refresh or ts is None or ts.expires < ( - time.time() + self.expiration_headroom): - token, expires_at = yield self.make_token_async( - self.scopes, self.service_account_id) - timeout = int(expires_at - time.time()) - ts = _AE_TokenStorage_(id=key, token=token, expires=expires_at) - if timeout > 0: - yield ts.put_async(memcache_timeout=timeout, - use_datastore=self.retry_params.save_access_token, - use_cache=True, use_memcache=True) - raise ndb.Return(ts.token) - - @ndb.tasklet - def urlfetch_async(self, url, method='GET', headers=None, - payload=None, deadline=None, callback=None, - follow_redirects=False): - """Make an async urlfetch() call. - - This is an async wrapper around urlfetch(). It adds an authentication - header. - - Args: - url: the url to fetch. - method: the method in which to fetch. - headers: the http headers. - payload: the data to submit in the fetch. - deadline: the deadline in which to make the call. - callback: the call to make once completed. - follow_redirects: whether or not to follow redirects. - - Yields: - This returns a Future despite not being decorated with @ndb.tasklet! - """ - headers = {} if headers is None else dict(headers) - headers.update(self.user_agent) - self.token = yield self.get_token_async() - if self.token: - headers['authorization'] = 'OAuth ' + self.token - - deadline = deadline or self.retry_params.urlfetch_timeout - - ctx = ndb.get_context() - resp = yield ctx.urlfetch( - url, payload=payload, method=method, - headers=headers, follow_redirects=follow_redirects, - deadline=deadline, callback=callback) - raise ndb.Return(resp) - - -_RestApi = add_sync_methods(_RestApi) diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/storage_api.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/storage_api.py deleted file mode 100755 index 910c365b..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/storage_api.py +++ /dev/null @@ -1,887 +0,0 @@ -# Copyright 2012 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Python wrappers for the Google Storage RESTful API.""" - - - - - -__all__ = ['ReadBuffer', - 'StreamingBuffer', - ] - -import collections -import os -import urlparse - -from . import api_utils -from . import common -from . import errors -from . import rest_api - -try: - from google.appengine.api import urlfetch - from google.appengine.ext import ndb -except ImportError: - from google.appengine.api import urlfetch - from google.appengine.ext import ndb - - - -def _get_storage_api(retry_params, account_id=None): - """Returns storage_api instance for API methods. - - Args: - retry_params: An instance of api_utils.RetryParams. If none, - thread's default will be used. - account_id: Internal-use only. - - Returns: - A storage_api instance to handle urlfetch work to GCS. - On dev appserver, this instance by default will talk to a local stub - unless common.ACCESS_TOKEN is set. That token will be used to talk - to the real GCS. - """ - - - api = _StorageApi(_StorageApi.full_control_scope, - service_account_id=account_id, - retry_params=retry_params) - if common.local_run() and not common.get_access_token(): - api.api_url = common.local_api_url() - if common.get_access_token(): - api.token = common.get_access_token() - return api - - -class _StorageApi(rest_api._RestApi): - """A simple wrapper for the Google Storage RESTful API. - - WARNING: Do NOT directly use this api. It's an implementation detail - and is subject to change at any release. - - All async methods have similar args and returns. - - Args: - path: The path to the Google Storage object or bucket, e.g. - '/mybucket/myfile' or '/mybucket'. - **kwd: Options for urlfetch. e.g. - headers={'content-type': 'text/plain'}, payload='blah'. - - Returns: - A ndb Future. When fulfilled, future.get_result() should return - a tuple of (status, headers, content) that represents a HTTP response - of Google Cloud Storage XML API. - """ - - api_url = 'https://storage.googleapis.com' - read_only_scope = 'https://www.googleapis.com/auth/devstorage.read_only' - read_write_scope = 'https://www.googleapis.com/auth/devstorage.read_write' - full_control_scope = 'https://www.googleapis.com/auth/devstorage.full_control' - - def __getstate__(self): - """Store state as part of serialization/pickling. - - Returns: - A tuple (of dictionaries) with the state of this object - """ - return (super(_StorageApi, self).__getstate__(), {'api_url': self.api_url}) - - def __setstate__(self, state): - """Restore state as part of deserialization/unpickling. - - Args: - state: the tuple from a __getstate__ call - """ - superstate, localstate = state - super(_StorageApi, self).__setstate__(superstate) - self.api_url = localstate['api_url'] - - @api_utils._eager_tasklet - @ndb.tasklet - def do_request_async(self, url, method='GET', headers=None, payload=None, - deadline=None, callback=None): - """Inherit docs. - - This method translates urlfetch exceptions to more service specific ones. - """ - if headers is None: - headers = {} - if 'x-goog-api-version' not in headers: - headers['x-goog-api-version'] = '2' - headers['accept-encoding'] = 'gzip, *' - try: - resp_tuple = yield super(_StorageApi, self).do_request_async( - url, method=method, headers=headers, payload=payload, - deadline=deadline, callback=callback) - except urlfetch.DownloadError, e: - raise errors.TimeoutError( - 'Request to Google Cloud Storage timed out.', e) - - raise ndb.Return(resp_tuple) - - - def post_object_async(self, path, **kwds): - """POST to an object.""" - return self.do_request_async(self.api_url + path, 'POST', **kwds) - - def put_object_async(self, path, **kwds): - """PUT an object.""" - return self.do_request_async(self.api_url + path, 'PUT', **kwds) - - def get_object_async(self, path, **kwds): - """GET an object. - - Note: No payload argument is supported. - """ - return self.do_request_async(self.api_url + path, 'GET', **kwds) - - def delete_object_async(self, path, **kwds): - """DELETE an object. - - Note: No payload argument is supported. - """ - return self.do_request_async(self.api_url + path, 'DELETE', **kwds) - - def head_object_async(self, path, **kwds): - """HEAD an object. - - Depending on request headers, HEAD returns various object properties, - e.g. Content-Length, Last-Modified, and ETag. - - Note: No payload argument is supported. - """ - return self.do_request_async(self.api_url + path, 'HEAD', **kwds) - - def get_bucket_async(self, path, **kwds): - """GET a bucket.""" - return self.do_request_async(self.api_url + path, 'GET', **kwds) - - -_StorageApi = rest_api.add_sync_methods(_StorageApi) - - -class ReadBuffer(object): - """A class for reading Google storage files.""" - - DEFAULT_BUFFER_SIZE = 1024 * 1024 - MAX_REQUEST_SIZE = 30 * DEFAULT_BUFFER_SIZE - - def __init__(self, - api, - path, - buffer_size=DEFAULT_BUFFER_SIZE, - max_request_size=MAX_REQUEST_SIZE): - """Constructor. - - Args: - api: A StorageApi instance. - path: Quoted/escaped path to the object, e.g. /mybucket/myfile - buffer_size: buffer size. The ReadBuffer keeps - one buffer. But there may be a pending future that contains - a second buffer. This size must be less than max_request_size. - max_request_size: Max bytes to request in one urlfetch. - """ - self._api = api - self._path = path - self.name = api_utils._unquote_filename(path) - self.closed = False - - assert buffer_size <= max_request_size - self._buffer_size = buffer_size - self._max_request_size = max_request_size - self._offset = 0 - self._buffer = _Buffer() - self._etag = None - - get_future = self._get_segment(0, self._buffer_size, check_response=False) - - status, headers, content = self._api.head_object(path) - errors.check_status(status, [200], path, resp_headers=headers, body=content) - self._file_size = long(common.get_stored_content_length(headers)) - self._check_etag(headers.get('etag')) - - self._buffer_future = None - - if self._file_size != 0: - content, check_response_closure = get_future.get_result() - check_response_closure() - self._buffer.reset(content) - self._request_next_buffer() - - def __getstate__(self): - """Store state as part of serialization/pickling. - - The contents of the read buffer are not stored, only the current offset for - data read by the client. A new read buffer is established at unpickling. - The head information for the object (file size and etag) are stored to - reduce startup and ensure the file has not changed. - - Returns: - A dictionary with the state of this object - """ - return {'api': self._api, - 'path': self._path, - 'buffer_size': self._buffer_size, - 'request_size': self._max_request_size, - 'etag': self._etag, - 'size': self._file_size, - 'offset': self._offset, - 'closed': self.closed} - - def __setstate__(self, state): - """Restore state as part of deserialization/unpickling. - - Args: - state: the dictionary from a __getstate__ call - - Along with restoring the state, pre-fetch the next read buffer. - """ - self._api = state['api'] - self._path = state['path'] - self.name = api_utils._unquote_filename(self._path) - self._buffer_size = state['buffer_size'] - self._max_request_size = state['request_size'] - self._etag = state['etag'] - self._file_size = state['size'] - self._offset = state['offset'] - self._buffer = _Buffer() - self.closed = state['closed'] - self._buffer_future = None - if self._remaining() and not self.closed: - self._request_next_buffer() - - def __iter__(self): - """Iterator interface. - - Note the ReadBuffer container itself is the iterator. It's - (quote PEP0234) - 'destructive: they consumes all the values and a second iterator - cannot easily be created that iterates independently over the same values. - You could open the file for the second time, or seek() to the beginning.' - - Returns: - Self. - """ - return self - - def next(self): - line = self.readline() - if not line: - raise StopIteration() - return line - - def readline(self, size=-1): - """Read one line delimited by '\n' from the file. - - A trailing newline character is kept in the string. It may be absent when a - file ends with an incomplete line. If the size argument is non-negative, - it specifies the maximum string size (counting the newline) to return. - A negative size is the same as unspecified. Empty string is returned - only when EOF is encountered immediately. - - Args: - size: Maximum number of bytes to read. If not specified, readline stops - only on '\n' or EOF. - - Returns: - The data read as a string. - - Raises: - IOError: When this buffer is closed. - """ - self._check_open() - if size == 0 or not self._remaining(): - return '' - - data_list = [] - newline_offset = self._buffer.find_newline(size) - while newline_offset < 0: - data = self._buffer.read(size) - size -= len(data) - self._offset += len(data) - data_list.append(data) - if size == 0 or not self._remaining(): - return ''.join(data_list) - self._buffer.reset(self._buffer_future.get_result()) - self._request_next_buffer() - newline_offset = self._buffer.find_newline(size) - - data = self._buffer.read_to_offset(newline_offset + 1) - self._offset += len(data) - data_list.append(data) - - return ''.join(data_list) - - def read(self, size=-1): - """Read data from RAW file. - - Args: - size: Number of bytes to read as integer. Actual number of bytes - read is always equal to size unless EOF is reached. If size is - negative or unspecified, read the entire file. - - Returns: - data read as str. - - Raises: - IOError: When this buffer is closed. - """ - self._check_open() - if not self._remaining(): - return '' - - data_list = [] - while True: - remaining = self._buffer.remaining() - if size >= 0 and size < remaining: - data_list.append(self._buffer.read(size)) - self._offset += size - break - else: - size -= remaining - self._offset += remaining - data_list.append(self._buffer.read()) - - if self._buffer_future is None: - if size < 0 or size >= self._remaining(): - needs = self._remaining() - else: - needs = size - data_list.extend(self._get_segments(self._offset, needs)) - self._offset += needs - break - - if self._buffer_future: - self._buffer.reset(self._buffer_future.get_result()) - self._buffer_future = None - - if self._buffer_future is None: - self._request_next_buffer() - return ''.join(data_list) - - def _remaining(self): - return self._file_size - self._offset - - def _request_next_buffer(self): - """Request next buffer. - - Requires self._offset and self._buffer are in consistent state. - """ - self._buffer_future = None - next_offset = self._offset + self._buffer.remaining() - if next_offset != self._file_size: - self._buffer_future = self._get_segment(next_offset, - self._buffer_size) - - def _get_segments(self, start, request_size): - """Get segments of the file from Google Storage as a list. - - A large request is broken into segments to avoid hitting urlfetch - response size limit. Each segment is returned from a separate urlfetch. - - Args: - start: start offset to request. Inclusive. Have to be within the - range of the file. - request_size: number of bytes to request. - - Returns: - A list of file segments in order - """ - if not request_size: - return [] - - end = start + request_size - futures = [] - - while request_size > self._max_request_size: - futures.append(self._get_segment(start, self._max_request_size)) - request_size -= self._max_request_size - start += self._max_request_size - if start < end: - futures.append(self._get_segment(start, end-start)) - return [fut.get_result() for fut in futures] - - @ndb.tasklet - def _get_segment(self, start, request_size, check_response=True): - """Get a segment of the file from Google Storage. - - Args: - start: start offset of the segment. Inclusive. Have to be within the - range of the file. - request_size: number of bytes to request. Have to be small enough - for a single urlfetch request. May go over the logical range of the - file. - check_response: True to check the validity of GCS response automatically - before the future returns. False otherwise. See Yields section. - - Yields: - If check_response is True, the segment [start, start + request_size) - of the file. - Otherwise, a tuple. The first element is the unverified file segment. - The second element is a closure that checks response. Caller should - first invoke the closure before consuing the file segment. - - Raises: - ValueError: if the file has changed while reading. - """ - end = start + request_size - 1 - content_range = '%d-%d' % (start, end) - headers = {'Range': 'bytes=' + content_range} - status, resp_headers, content = yield self._api.get_object_async( - self._path, headers=headers) - def _checker(): - errors.check_status(status, [200, 206], self._path, headers, - resp_headers, body=content) - self._check_etag(resp_headers.get('etag')) - if check_response: - _checker() - raise ndb.Return(content) - raise ndb.Return(content, _checker) - - def _check_etag(self, etag): - """Check if etag is the same across requests to GCS. - - If self._etag is None, set it. If etag is set, check that the new - etag equals the old one. - - In the __init__ method, we fire one HEAD and one GET request using - ndb tasklet. One of them would return first and set the first value. - - Args: - etag: etag from a GCS HTTP response. None if etag is not part of the - response header. It could be None for example in the case of GCS - composite file. - - Raises: - ValueError: if two etags are not equal. - """ - if etag is None: - return - elif self._etag is None: - self._etag = etag - elif self._etag != etag: - raise ValueError('File on GCS has changed while reading.') - - def close(self): - self.closed = True - self._buffer = None - self._buffer_future = None - - def __enter__(self): - return self - - def __exit__(self, atype, value, traceback): - self.close() - return False - - def seek(self, offset, whence=os.SEEK_SET): - """Set the file's current offset. - - Note if the new offset is out of bound, it is adjusted to either 0 or EOF. - - Args: - offset: seek offset as number. - whence: seek mode. Supported modes are os.SEEK_SET (absolute seek), - os.SEEK_CUR (seek relative to the current position), and os.SEEK_END - (seek relative to the end, offset should be negative). - - Raises: - IOError: When this buffer is closed. - ValueError: When whence is invalid. - """ - self._check_open() - - self._buffer.reset() - self._buffer_future = None - - if whence == os.SEEK_SET: - self._offset = offset - elif whence == os.SEEK_CUR: - self._offset += offset - elif whence == os.SEEK_END: - self._offset = self._file_size + offset - else: - raise ValueError('Whence mode %s is invalid.' % str(whence)) - - self._offset = min(self._offset, self._file_size) - self._offset = max(self._offset, 0) - if self._remaining(): - self._request_next_buffer() - - def tell(self): - """Tell the file's current offset. - - Returns: - current offset in reading this file. - - Raises: - IOError: When this buffer is closed. - """ - self._check_open() - return self._offset - - def _check_open(self): - if self.closed: - raise IOError('Buffer is closed.') - - def seekable(self): - return True - - def readable(self): - return True - - def writable(self): - return False - - -class _Buffer(object): - """In memory buffer.""" - - def __init__(self): - self.reset() - - def reset(self, content='', offset=0): - self._buffer = content - self._offset = offset - - def read(self, size=-1): - """Returns bytes from self._buffer and update related offsets. - - Args: - size: number of bytes to read starting from current offset. - Read the entire buffer if negative. - - Returns: - Requested bytes from buffer. - """ - if size < 0: - offset = len(self._buffer) - else: - offset = self._offset + size - return self.read_to_offset(offset) - - def read_to_offset(self, offset): - """Returns bytes from self._buffer and update related offsets. - - Args: - offset: read from current offset to this offset, exclusive. - - Returns: - Requested bytes from buffer. - """ - assert offset >= self._offset - result = self._buffer[self._offset: offset] - self._offset += len(result) - return result - - def remaining(self): - return len(self._buffer) - self._offset - - def find_newline(self, size=-1): - """Search for newline char in buffer starting from current offset. - - Args: - size: number of bytes to search. -1 means all. - - Returns: - offset of newline char in buffer. -1 if doesn't exist. - """ - if size < 0: - return self._buffer.find('\n', self._offset) - return self._buffer.find('\n', self._offset, self._offset + size) - - -class StreamingBuffer(object): - """A class for creating large objects using the 'resumable' API. - - The API is a subset of the Python writable stream API sufficient to - support writing zip files using the zipfile module. - - The exact sequence of calls and use of headers is documented at - https://developers.google.com/storage/docs/developer-guide#unknownresumables - """ - - _blocksize = 256 * 1024 - - _flushsize = 8 * _blocksize - - _maxrequestsize = 9 * 4 * _blocksize - - def __init__(self, - api, - path, - content_type=None, - gcs_headers=None): - """Constructor. - - Args: - api: A StorageApi instance. - path: Quoted/escaped path to the object, e.g. /mybucket/myfile - content_type: Optional content-type; Default value is - delegate to Google Cloud Storage. - gcs_headers: additional gs headers as a str->str dict, e.g - {'x-goog-acl': 'private', 'x-goog-meta-foo': 'foo'}. - Raises: - IOError: When this location can not be found. - """ - assert self._maxrequestsize > self._blocksize - assert self._maxrequestsize % self._blocksize == 0 - assert self._maxrequestsize >= self._flushsize - - self._api = api - self._path = path - - self.name = api_utils._unquote_filename(path) - self.closed = False - - self._buffer = collections.deque() - self._buffered = 0 - self._written = 0 - self._offset = 0 - - headers = {'x-goog-resumable': 'start'} - if content_type: - headers['content-type'] = content_type - if gcs_headers: - headers.update(gcs_headers) - status, resp_headers, content = self._api.post_object(path, headers=headers) - errors.check_status(status, [201], path, headers, resp_headers, - body=content) - loc = resp_headers.get('location') - if not loc: - raise IOError('No location header found in 201 response') - parsed = urlparse.urlparse(loc) - self._path_with_token = '%s?%s' % (self._path, parsed.query) - - def __getstate__(self): - """Store state as part of serialization/pickling. - - The contents of the write buffer are stored. Writes to the underlying - storage are required to be on block boundaries (_blocksize) except for the - last write. In the worst case the pickled version of this object may be - slightly larger than the blocksize. - - Returns: - A dictionary with the state of this object - - """ - return {'api': self._api, - 'path': self._path, - 'path_token': self._path_with_token, - 'buffer': self._buffer, - 'buffered': self._buffered, - 'written': self._written, - 'offset': self._offset, - 'closed': self.closed} - - def __setstate__(self, state): - """Restore state as part of deserialization/unpickling. - - Args: - state: the dictionary from a __getstate__ call - """ - self._api = state['api'] - self._path_with_token = state['path_token'] - self._buffer = state['buffer'] - self._buffered = state['buffered'] - self._written = state['written'] - self._offset = state['offset'] - self.closed = state['closed'] - self._path = state['path'] - self.name = api_utils._unquote_filename(self._path) - - def write(self, data): - """Write some bytes. - - Args: - data: data to write. str. - - Raises: - TypeError: if data is not of type str. - """ - self._check_open() - if not isinstance(data, str): - raise TypeError('Expected str but got %s.' % type(data)) - if not data: - return - self._buffer.append(data) - self._buffered += len(data) - self._offset += len(data) - if self._buffered >= self._flushsize: - self._flush() - - def flush(self): - """Flush as much as possible to GCS. - - GCS *requires* that all writes except for the final one align on - 256KB boundaries. So the internal buffer may still have < 256KB bytes left - after flush. - """ - self._check_open() - self._flush(finish=False) - - def tell(self): - """Return the total number of bytes passed to write() so far. - - (There is no seek() method.) - """ - return self._offset - - def close(self): - """Flush the buffer and finalize the file. - - When this returns the new file is available for reading. - """ - if not self.closed: - self.closed = True - self._flush(finish=True) - self._buffer = None - - def __enter__(self): - return self - - def __exit__(self, atype, value, traceback): - self.close() - return False - - def _flush(self, finish=False): - """Internal API to flush. - - Buffer is flushed to GCS only when the total amount of buffered data is at - least self._blocksize, or to flush the final (incomplete) block of - the file with finish=True. - """ - while ((finish and self._buffered >= 0) or - (not finish and self._buffered >= self._blocksize)): - tmp_buffer = [] - tmp_buffer_len = 0 - - excess = 0 - while self._buffer: - buf = self._buffer.popleft() - size = len(buf) - self._buffered -= size - tmp_buffer.append(buf) - tmp_buffer_len += size - if tmp_buffer_len >= self._maxrequestsize: - excess = tmp_buffer_len - self._maxrequestsize - break - if not finish and ( - tmp_buffer_len % self._blocksize + self._buffered < - self._blocksize): - excess = tmp_buffer_len % self._blocksize - break - - if excess: - over = tmp_buffer.pop() - size = len(over) - assert size >= excess - tmp_buffer_len -= size - head, tail = over[:-excess], over[-excess:] - self._buffer.appendleft(tail) - self._buffered += len(tail) - if head: - tmp_buffer.append(head) - tmp_buffer_len += len(head) - - data = ''.join(tmp_buffer) - file_len = '*' - if finish and not self._buffered: - file_len = self._written + len(data) - self._send_data(data, self._written, file_len) - self._written += len(data) - if file_len != '*': - break - - def _send_data(self, data, start_offset, file_len): - """Send the block to the storage service. - - This is a utility method that does not modify self. - - Args: - data: data to send in str. - start_offset: start offset of the data in relation to the file. - file_len: an int if this is the last data to append to the file. - Otherwise '*'. - """ - headers = {} - end_offset = start_offset + len(data) - 1 - - if data: - headers['content-range'] = ('bytes %d-%d/%s' % - (start_offset, end_offset, file_len)) - else: - headers['content-range'] = ('bytes */%s' % file_len) - - status, response_headers, content = self._api.put_object( - self._path_with_token, payload=data, headers=headers) - if file_len == '*': - expected = 308 - else: - expected = 200 - errors.check_status(status, [expected], self._path, headers, - response_headers, content, - {'upload_path': self._path_with_token}) - - def _get_offset_from_gcs(self): - """Get the last offset that has been written to GCS. - - This is a utility method that does not modify self. - - Returns: - an int of the last offset written to GCS by this upload, inclusive. - -1 means nothing has been written. - """ - headers = {'content-range': 'bytes */*'} - status, response_headers, content = self._api.put_object( - self._path_with_token, headers=headers) - errors.check_status(status, [308], self._path, headers, - response_headers, content, - {'upload_path': self._path_with_token}) - val = response_headers.get('range') - if val is None: - return -1 - _, offset = val.rsplit('-', 1) - return int(offset) - - def _force_close(self, file_length=None): - """Close this buffer on file_length. - - Finalize this upload immediately on file_length. - Contents that are still in memory will not be uploaded. - - This is a utility method that does not modify self. - - Args: - file_length: file length. Must match what has been uploaded. If None, - it will be queried from GCS. - """ - if file_length is None: - file_length = self._get_offset_from_gcs() + 1 - self._send_data('', 0, file_length) - - def _check_open(self): - if self.closed: - raise IOError('Buffer is closed.') - - def seekable(self): - return False - - def readable(self): - return False - - def writable(self): - return True diff --git a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/test_utils.py b/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/test_utils.py deleted file mode 100755 index e4d82477..00000000 --- a/src/tools/google_trace_viewer/perf_insights/third_party/cloudstorage/test_utils.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2013 Google Inc. All Rights Reserved. -# -# 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 -# -# 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. - -"""Utils for testing.""" - - -class MockUrlFetchResult(object): - - def __init__(self, status, headers, body): - self.status_code = status - self.headers = headers - self.content = body - self.content_was_truncated = False - self.final_url = None diff --git a/src/tools/google_trace_viewer/tracing/.allow-devtools-save b/src/tools/google_trace_viewer/tracing/.allow-devtools-save deleted file mode 100755 index e69de29b..00000000 diff --git a/src/tools/google_trace_viewer/tracing/.bowerrc b/src/tools/google_trace_viewer/tracing/.bowerrc deleted file mode 100755 index d981a1dd..00000000 --- a/src/tools/google_trace_viewer/tracing/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "third_party/components" -} diff --git a/src/tools/google_trace_viewer/tracing/.gitignore b/src/tools/google_trace_viewer/tracing/.gitignore deleted file mode 100755 index c17a21f6..00000000 --- a/src/tools/google_trace_viewer/tracing/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.pyc -*.swp -.idea -.DS_Store -*~ -.project -.settings -bin/trace_viewer*.html -test_data/measurmt-traces diff --git a/src/tools/google_trace_viewer/tracing/AUTHORS b/src/tools/google_trace_viewer/tracing/AUTHORS deleted file mode 100755 index 5a7ed829..00000000 --- a/src/tools/google_trace_viewer/tracing/AUTHORS +++ /dev/null @@ -1,12 +0,0 @@ -# Names should be added to this file with this pattern: -# -# For individuals: -# Name -# -# For organizations: -# Organization -# -# See python fnmatch module documentation for more information. - -The Chromium Authors <*@chromium.org> -Google Inc. <*@google.com> diff --git a/src/tools/google_trace_viewer/tracing/BUILD.gn b/src/tools/google_trace_viewer/tracing/BUILD.gn deleted file mode 100755 index c2ce3eb4..00000000 --- a/src/tools/google_trace_viewer/tracing/BUILD.gn +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -gypi_values = exec_script("//build/gypi_to_gn.py", - [ rebase_path("trace_viewer.gypi") ], - "scope", - [ "trace_viewer.gypi" ]) - -# TODO: ideally this would go into the target_gen_dir, but this requires some -# changes to the scripts that process them. -output_resource_dir = "$root_gen_dir/content/browser/tracing" - -action("generate_about_tracing") { - script = "build/generate_about_tracing_contents" - - inputs = gypi_values.tracing_css_files + gypi_values.tracing_js_html_files + - gypi_values.tracing_img_files - outputs = [ - "$output_resource_dir/about_tracing.js", - "$output_resource_dir/about_tracing.html", - ] - - args = [ - "--outdir", rebase_path(output_resource_dir, root_build_dir), - ] -} diff --git a/src/tools/google_trace_viewer/tracing/LICENSE b/src/tools/google_trace_viewer/tracing/LICENSE deleted file mode 100755 index e6c0d72a..00000000 --- a/src/tools/google_trace_viewer/tracing/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * 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. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "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 THE COPYRIGHT -// OWNER 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. diff --git a/src/tools/google_trace_viewer/tracing/OWNERS b/src/tools/google_trace_viewer/tracing/OWNERS deleted file mode 100755 index 72e8ffc0..00000000 --- a/src/tools/google_trace_viewer/tracing/OWNERS +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/src/tools/google_trace_viewer/tracing/PRESUBMIT.py b/src/tools/google_trace_viewer/tracing/PRESUBMIT.py deleted file mode 100755 index 1c1bf199..00000000 --- a/src/tools/google_trace_viewer/tracing/PRESUBMIT.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import sys - -def RunChecks(depot_tools_input_api, depot_tools_output_api): - from build import tv_input_api - input_api = tv_input_api.TvInputAPI(depot_tools_input_api) - - results = [] - from tracing.build import check_gypi - err = check_gypi.GypiCheck() - if err: - results += [err] - - from tracing.build import check_modules - err = check_modules.CheckModules() - if err: - results += [err] - - from tracing.build import js_checks - results += js_checks.RunChecks(input_api) - - return map(depot_tools_output_api.PresubmitError, results) - -def CheckChange(input_api, output_api): - original_sys_path = sys.path - try: - sys.path += [input_api.PresubmitLocalPath()] - return RunChecks(input_api, output_api) - finally: - sys.path = original_sys_path - -def CheckChangeOnUpload(input_api, output_api): - return CheckChange(input_api, output_api) - -def CheckChangeOnCommit(input_api, output_api): - return CheckChange(input_api, output_api) diff --git a/src/tools/google_trace_viewer/tracing/__init__.py b/src/tools/google_trace_viewer/tracing/__init__.py deleted file mode 100755 index b471136b..00000000 --- a/src/tools/google_trace_viewer/tracing/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -def _SetupTVCMPath(): - tvcm_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - 'third_party', 'tvcm')) - if tvcm_path not in sys.path: - sys.path.append(tvcm_path) - -_SetupTVCMPath() diff --git a/src/tools/google_trace_viewer/tracing/app.yaml b/src/tools/google_trace_viewer/tracing/app.yaml deleted file mode 100755 index e2a265a3..00000000 --- a/src/tools/google_trace_viewer/tracing/app.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -runtime: python27 -threadsafe: true -api_version: 1 - -handlers: - -- url: /base - static_dir: tracing/tracing/base - secure: always - -- url: /core - static_dir: tracing/tracing/core - secure: always - -- url: /extras - static_dir: tracing/tracing/extras - secure: always - -- url: /ui - static_dir: tracing/tracing/ui - secure: always - -- url: /components - static_dir: tracing/third_party/components - secure: always - -- url: /trace_viewer - static_dir: tracing/tracing - secure: always - -- url: /gl-matrix-min.js - static_files: tracing/third_party/gl-matrix/dist/gl-matrix-min.js - upload: tracing/third_party/gl-matrix/dist/gl-matrix-min.js - secure: always - -- url: /jszip.min.js - static_files: tracing/third_party/jszip/jszip.min.js - upload: tracing/third_party/jszip/jszip.min.js - secure: always - -- url: /d3.min.js - static_files: tracing/third_party/d3/d3.min.js - upload: tracing/third_party/d3/d3.min.js - secure: always - -- url: /.* - static_files: tracing/tracing/ui/extras/drive/index.html - upload: tracing/tracing/ui/extras/drive/index.html - secure: always diff --git a/src/tools/google_trace_viewer/tracing/bin/index.html b/src/tools/google_trace_viewer/tracing/bin/index.html deleted file mode 100755 index eea5c2ee..00000000 --- a/src/tools/google_trace_viewer/tracing/bin/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - diff --git a/src/tools/google_trace_viewer/tracing/bower.json b/src/tools/google_trace_viewer/tracing/bower.json deleted file mode 100755 index 429f8995..00000000 --- a/src/tools/google_trace_viewer/tracing/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "trace-viewer", - "version": "0.0.0", - "homepage": "http://google.github.io/trace-viewer", - "authors": [ - "Nat Duca ", - "dan sinclair " - ], - "description": "TraceViewer for chrome://tracing and Android Systrace", - "license": "BSD", - "private": true, - "ignore": [ - "**/.*", - "node_modules", - "trace-viewer/components", - "test", - "tests" - ], - "dependencies": { - "polymer": "Polymer/polymer#~0.5.5" - } -} diff --git a/src/tools/google_trace_viewer/tracing/build/__init__.py b/src/tools/google_trace_viewer/tracing/build/__init__.py deleted file mode 100755 index ffbe162a..00000000 --- a/src/tools/google_trace_viewer/tracing/build/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# diff --git a/src/tools/google_trace_viewer/tracing/build/benchmarks.py b/src/tools/google_trace_viewer/tracing/build/benchmarks.py deleted file mode 100755 index 194d23bf..00000000 --- a/src/tools/google_trace_viewer/tracing/build/benchmarks.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import cProfile, pstats, StringIO -import inspect -import optparse -import sys - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project - -class Bench(object): - def SetUp(self): - pass - def Run(self): - pass - def TearDown(self): - pass - -class CalcDepsBench(Bench): - def Run(self): - project = tracing_project.TracingProject() - load_sequence = project.CalcLoadSequenceForAllModules() - -class FindAllModuleFilenamesBench(Bench): - def Run(self): - project = tracing_project.TracingProject() - filenames = project.FindAllModuleFilenames() - -class DoGenerate(Bench): - def SetUp(): - self.project = tracing_project.TracingProject() - self.load_sequence = project.CalcLoadSequenceForAllModules() - - def Run(self): - self.deps = generate.GenerateDepsJS( - self.load_sequence, self.project) - - -def Main(args): - parser = optparse.OptionParser() - parser.add_option('--repeat-count', type='int', - default=10) - options, args = parser.parse_args(args) - - benches = [g for g in globals().values() - if g != Bench and inspect.isclass(g) and Bench in inspect.getmro(g)] - if len(args) != 1: - sys.stderr.write('\n'.join([b.__name__ for b in benches])) - return 1 - - b = [b for b in benches if b.__name__ == args[0]] - if len(b) != 1: - sys.stderr.write('Oops') - return 1 - - bench = b[0]() - bench.SetUp() - try: - pr = cProfile.Profile() - pr.enable(builtins=False) - for i in range(options.repeat_count): - bench.Run() - pr.disable() - s = StringIO.StringIO() - - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - return 0 - finally: - bench.TearDown() - -if __name__ == '__main__': - sys.exit(Main(sys.argv[1:])) diff --git a/src/tools/google_trace_viewer/tracing/build/check_common.py b/src/tools/google_trace_viewer/tracing/build/check_common.py deleted file mode 100755 index 23556a79..00000000 --- a/src/tools/google_trace_viewer/tracing/build/check_common.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys -import os - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project - - -FILE_GROUPS = ["tracing_css_files", - "tracing_js_html_files", - "tracing_img_files"] - -def GetFileGroupFromFileName(filename): - extension = os.path.splitext(filename)[1] - return { - '.css': 'tracing_css_files', - '.html': 'tracing_js_html_files', - '.js': 'tracing_js_html_files', - '.png': 'tracing_img_files' - }[extension] - -def CheckListedFilesSorted(src_file, group_name, listed_files): - sorted_files = sorted(listed_files) - if sorted_files != listed_files: - mismatch = '' - for i in range(len(listed_files)): - if listed_files[i] != sorted_files[i]: - mismatch = listed_files[i] - break - what_is = ' ' + '\n '.join(listed_files) - what_should_be = ' ' + '\n '.join(sorted_files) - return '''In group {0} from file {1}, filenames aren't sorted. - -First mismatch: - {2} - -Current listing: -{3} - -Correct listing: -{4}\n\n'''.format(group_name, src_file, mismatch, what_is, what_should_be) - else: - return '' - -def GetKnownFiles(): - p = tracing_project.TracingProject() - m = p.loader.LoadModule(module_name='ui.extras.about_tracing.about_tracing') - absolute_filenames = m.GetAllDependentFilenamesRecursive( - include_raw_scripts=False) - - return list(set([os.path.relpath(f, p.tracing_root_path) - for f in absolute_filenames])) - -def CheckCommon(file_name, listed_files): - project = tracing_project.TracingProject() - - known_files = GetKnownFiles() - u = set(listed_files).union(set(known_files)) - i = set(listed_files).intersection(set(known_files)) - diff = list(u - i) - - if len(diff) == 0: - return '' - - error = 'Entries in ' + file_name + ' do not match files on disk:\n' - in_file_only = list(set(listed_files) - set(known_files)) - in_known_only = list(set(known_files) - set(listed_files)) - - if len(in_file_only) > 0: - error += ' In file only:\n ' + '\n '.join(sorted(in_file_only)) - if len(in_known_only) > 0: - if len(in_file_only) > 0: - error += '\n\n' - error += ' On disk only:\n ' + '\n '.join(sorted(in_known_only)) - - if in_file_only: - error += ('\n\n' - ' Note: only files actually used in about:tracing should\n' - ' be listed in the build files. Try running build/update_gyp_and_gn\n' - ' to update the files automatically.') - - return error diff --git a/src/tools/google_trace_viewer/tracing/build/check_common_unittest.py b/src/tools/google_trace_viewer/tracing/build/check_common_unittest.py deleted file mode 100755 index 76b6ad5f..00000000 --- a/src/tools/google_trace_viewer/tracing/build/check_common_unittest.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import unittest - -from tracing.build import check_common - -class CheckCommonUnittTest(unittest.TestCase): - def test_filesSortedTest(self): - error = check_common.CheckListedFilesSorted('foo.gyp', 'tracing_pdf_files', - ['/dir/file.pdf', - '/dir/another_file.pdf']) - expected_error = '''In group tracing_pdf_files from file foo.gyp,\ - filenames aren't sorted. - -First mismatch: - /dir/file.pdf - -Current listing: - /dir/file.pdf - /dir/another_file.pdf - -Correct listing: - /dir/another_file.pdf - /dir/file.pdf\n\n''' - assert error == expected_error diff --git a/src/tools/google_trace_viewer/tracing/build/check_gypi.py b/src/tools/google_trace_viewer/tracing/build/check_gypi.py deleted file mode 100755 index 072334f6..00000000 --- a/src/tools/google_trace_viewer/tracing/build/check_gypi.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys -import os - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing.build import check_common - -GYPI_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', 'trace_viewer.gypi')) - -def GypiCheck(): - f = open(GYPI_FILE, 'r') - gyp = f.read() - f.close() - - data = eval(gyp) - listed_files = [] - error = '' - for group in check_common.FILE_GROUPS: - filenames = map(os.path.normpath, data['variables'][group]) - error += check_common.CheckListedFilesSorted(GYPI_FILE, group, filenames) - listed_files.extend(filenames) - - return error + check_common.CheckCommon(GYPI_FILE, listed_files) - -if __name__ == '__main__': - print GypiCheck() diff --git a/src/tools/google_trace_viewer/tracing/build/check_modules.py b/src/tools/google_trace_viewer/tracing/build/check_modules.py deleted file mode 100755 index 374554ec..00000000 --- a/src/tools/google_trace_viewer/tracing/build/check_modules.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys -import os - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project - -def CheckModules(): - p = tracing_project.TracingProject() - try: - p.CalcLoadSequenceForAllModules() - except Exception, ex: - return str(ex) - return [] - -if __name__ == '__main__': - print GypCheck() diff --git a/src/tools/google_trace_viewer/tracing/build/css_presubmit_checker.py b/src/tools/google_trace_viewer/tracing/build/css_presubmit_checker.py deleted file mode 100755 index a99383c5..00000000 --- a/src/tools/google_trace_viewer/tracing/build/css_presubmit_checker.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import re - -class CSSChecker(object): - def __init__(self, input_api, output_api, file_filter=None): - self.input_api = input_api - self.output_api = output_api - self.file_filter = file_filter - - def RunChecks(self): - # We use this a lot, so make a nick name variable. - def _collapseable_hex(s): - return (len(s) == 6 and s[0] == s[1] and s[2] == s[3] and s[4] == s[5]) - - def _is_gray(s): - return s[0] == s[1] == s[2] if len(s) == 3 else s[0:2] == s[2:4] == s[4:6] - - def _remove_all(s): - return _remove_grit(_remove_ats(_remove_comments(s))) - - def _remove_ats(s): - return re.sub(re.compile(r'@\w+.*?{(.*{.*?})+.*?}', re.DOTALL), '\\1', s) - - def _remove_comments(s): - return re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', s) - - def _remove_grit(s): - grit_reg = r']+>.*?<\s*/\s*if[^>]*>|]+>' - return re.sub(re.compile(grit_reg, re.DOTALL), '', s) - - def _rgb_from_hex(s): - if len(s) == 3: - r, g, b = s[0] + s[0], s[1] + s[1], s[2] + s[2] - else: - r, g, b = s[0:2], s[2:4], s[4:6] - return int(r, base=16), int(g, base=16), int(b, base=16) - - def alphabetize_props(contents): - errors = [] - for rule in re.finditer(r'{(.*?)}', contents, re.DOTALL): - semis = map(lambda t: t.strip(), rule.group(1).split(';'))[:-1] - rules = filter(lambda r: ': ' in r, semis) - props = map(lambda r: r[0:r.find(':')], rules) - if props != sorted(props): - errors.append(' %s;\nExpected: %s' % ( - ';\n '.join(rules), ','.join(list(sorted(props))))) - return errors - - def braces_have_space_before_and_nothing_after(line): - return re.search(r'(?:^|\S){|{\s*\S+\s*$', line) - - def classes_use_dashes(line): - # Intentionally dumbed down version of CSS 2.1 grammar for class without - # non-ASCII, escape chars, or whitespace. - m = re.search(r'\.(-?[_a-zA-Z0-9-]+).*[,{]\s*$', line) - return (m and (m.group(1).lower() != m.group(1) or - m.group(1).find('_') >= 0)) - - # Ignore single frames in a @keyframe, i.e. 0% { margin: 50px; } - frame_reg = r'\s*\d+%\s*{\s*[_a-zA-Z0-9-]+:(\s*[_a-zA-Z0-9-]+)+\s*;\s*}\s*' - def close_brace_on_new_line(line): - return (line.find('}') >= 0 and re.search(r'[^ }]', line) and - not re.match(frame_reg, line)) - - def colons_have_space_after(line): - return re.search(r'(?= 0 - - # Shared between hex_could_be_shorter and rgb_if_not_gray. - hex_reg = (r'#([a-fA-F0-9]{3}|[a-fA-F0-9]{6})(?=[^_a-zA-Z0-9-]|$)' - r'(?!.*(?:{.*|,\s*)$)') - def hex_could_be_shorter(line): - m = re.search(hex_reg, line) - return (m and _is_gray(m.group(1)) and _collapseable_hex(m.group(1))) - - small_seconds = r'(?:^|[^_a-zA-Z0-9-])(0?\.[0-9]+)s(?!-?[_a-zA-Z0-9-])' - def milliseconds_for_small_times(line): - return re.search(small_seconds, line) - - def no_data_uris_in_source_files(line): - return re.search(r'\(\s*\'?\s*data:', line) - - def one_rule_per_line(line): - return re.search(r'[_a-zA-Z0-9-](? tags; we're - # not using a real parser. TODO(dbeam): Check alpha in blocks. - file_contents = _remove_all('\n'.join(f.new_contents)) - files.append((f.filename, file_contents)) - - # Only look at CSS files for now. - for f in filter(lambda f: f[0].endswith('.css'), files): - file_errors = [] - for check in added_or_modified_files_checks: - # If the check is multiline, it receieves the whole file and gives us - # back a list of things wrong. If the check isn't multiline, we pass it - # each line and the check returns something truthy if there's an issue. - if ('multiline' in check and check['multiline']): - check_errors = check['test'](f[1]) - if len(check_errors) > 0: - # There are currently no multiline checks with ['after']. - file_errors.append('- %s\n%s' % - (check['desc'], '\n'.join(check_errors).rstrip())) - else: - check_errors = [] - lines = f[1].splitlines() - for lnum in range(0, len(lines)): - line = lines[lnum] - if check['test'](line): - error = ' ' + line.strip() - if 'after' in check: - error += check['after'](line) - check_errors.append(error) - if len(check_errors) > 0: - file_errors.append('- %s\n%s' % - (check['desc'], '\n'.join(check_errors))) - if file_errors: - results.append(self.output_api.PresubmitPromptWarning( - '%s:\n%s' % (f[0], '\n\n'.join(file_errors)))) - - if results: - # Add your name if you're here often mucking around in the code. - authors = ['dbeam@chromium.org'] - results.append(self.output_api.PresubmitNotifyResult( - 'Was the CSS checker useful? Send feedback or hate mail to %s.' % - ', '.join(authors))) - - return results diff --git a/src/tools/google_trace_viewer/tracing/build/d8_bootstrap.js b/src/tools/google_trace_viewer/tracing/build/d8_bootstrap.js deleted file mode 100755 index aabea13d..00000000 --- a/src/tools/google_trace_viewer/tracing/build/d8_bootstrap.js +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Boostrap for loading javascript/html files using d8_runner. - */ -(function(global, v8arguments) { - // Save the argv in a predictable and stable location. - global.sys = { - argv: [] - }; - for (var i = 0; i < v8arguments.length; i++) - sys.argv.push(v8arguments[i]); - - /* There are four ways a program can finish running in D8: - * - a) Intentioned exit triggered via quit(0) - * - b) Intentioned exit triggered via quit(n) - * - c) Running to end of the script - * - d) An uncaught exception - * - * The exit code of d8 for case a is 0. - * The exit code of d8 for case b is unsigned(n) & 0xFF - * The exit code of d8 for case c is 0. - * The exit code of d8 for case d is 1. - * - * D8 runner needs to distinguish between these cases: - * - a) _ExecuteFileWithD8 should return 0 - * - b) _ExecuteFileWithD8 should return n - * - c) _ExecuteFileWithD8 should return 0 - * - d) _ExecuteFileWithD8 should raise an Exception - * - * The hard one here is d and b with n=1, because they fight for the same - * return code. - * - * Our solution is to monkeypatch quit() s.t. quit(1) becomes exitcode=2. - * This makes quit(255) disallowed, but it ensures that D8 runner is able - * to handle the other cases correctly. - */ - var realQuit = global.quit; - global.quit = function(exitCode) { - // Normalize the exit code. - if (exitCode < 0) { - exitCode = (exitCode % 256) + 256; - } else { - exitCode = exitCode % 256; - } - - // 255 is reserved due to reasons noted above. - if (exitCode == 255) - throw new Error('exitCodes 255 is reserved, sorry.'); - if (exitCode === 0) - realQuit(0); - realQuit(exitCode + 1); - } - - /** - * Polyfills console's methods. - */ - global.console = { - log: function() { - var args = Array.prototype.slice.call(arguments); - print(args.join(' ')); - }, - - info: function() { - var args = Array.prototype.slice.call(arguments); - print('Info:', args.join(' ')); - }, - - error: function() { - var args = Array.prototype.slice.call(arguments); - print('Error:', args.join(' ')); - }, - - warn: function() { - var args = Array.prototype.slice.call(arguments); - print('Warning:', args.join(' ')); - } - }; - - if (os.chdir) { - os.chdir = function() { - throw new Error('Dont do this'); - } - } - - /* This is a Base64 Polyfill adapted from - * https://github.com/davidchambers/Base64.js/blob/0.3.0/, - * which has a "do whatever you want" license, - * https://github.com/davidchambers/Base64.js/blob/0.3.0/LICENSE. - */ - (function() { - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + - '0123456789+/='; - - function InvalidCharacterError(message) { - this.message = message; - } - InvalidCharacterError.prototype = new Error; - InvalidCharacterError.prototype.name = 'InvalidCharacterError'; - - - // encoder - // [https://gist.github.com/999166] by [https://github.com/nignag] - global.btoa = function(input) { - var str = String(input); - for ( - // Initialize result and counter. - var block, charCode, idx = 0, map = chars, output = ''; - // If the next str index does not exist: - // change the mapping table to "=" - // check if d has no fractional digits - str.charAt(idx | 0) || (map = '=', idx % 1); - // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8. - output += map.charAt(63 & block >> 8 - idx % 1 * 8)) { - charCode = str.charCodeAt(idx += 3 / 4); - if (charCode > 0xFF) { - throw new InvalidCharacterError( - '\'btoa\' failed: The string to be encoded contains characters ' + - 'outside of the Latin1 range.'); - } - block = block << 8 | charCode; - } - return output; - }; - - // decoder - // [https://gist.github.com/1020396] by [https://github.com/atk] - global.atob = function(input) { - var str = String(input).replace(/=+$/, ''); - if (str.length % 4 == 1) { - throw new InvalidCharacterError( - '\'atob\' failed: The string to be decoded is not ' + - 'correctly encoded.'); - } - for ( - // Initialize result and counters. - var bc = 0, bs, buffer, idx = 0, output = ''; - // Get next character. - buffer = str.charAt(idx++); - // Character found in table? initialize bit storage and add its - // ascii value; - ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, - // And if not first of each 4 characters, - // convert the first 8 bits to one ascii character. - bc++ % 4) ? output += String.fromCharCode( - 255 & bs >> (-2 * bc & 6)) : 0) { - // Try to find character in table (0-63, not found => -1). - buffer = chars.indexOf(buffer); - } - return output; - }; - - })(); - - // Bring in path utils. - load('<%path_utils_js_path%>'); - PathUtils.currentWorkingDirectory = '<%current_working_directory%>'; - - /** - * Strips the starting '/' in file_path if |file_path| is meant to be a - * relative path. - * - * @param {string} file_path path to some file, can be relative or absolute - * path. - * @return {string} the file_path with starting '/' removed if |file_path| - * does not exist or the original |file_path| otherwise. - */ - function _stripStartingSlashIfNeeded(file_path) { - if (file_path.substring(0, 1) !== '/') { - return file_path; - } - if (PathUtils.exists(file_path)) - return file_path; - return file_path.substring(1); - } - - var sourcePaths = JSON.parse('<%source_paths%>'); - - global.hrefToAbsolutePath = function(href) { - var pathPart; - if (!PathUtils.isAbs(href)) { - throw new Error('Found a non absolute import and thats not supported: ' + - href); - } else { - pathPart = href.substring(1); - } - - candidates = []; - for (var i = 0; i < sourcePaths.length; i++) { - var candidate = PathUtils.join(sourcePaths[i], pathPart); - if (PathUtils.exists(candidate)) - candidates.push(candidate); - } - if (candidates.length > 1) - throw new Error('Multiple candidates found for ' + href); - if (candidates.length === 0) - throw new Error(href + ' not found!'); - return candidates[0]; - } - - var loadedModulesByFilePath = {}; - - /** - * Load a HTML file, which absolute path or path relative to <%search-path%>. - * Unlike the native load() method of d8, variables declared in |file_path| - * will not be hoisted to the caller environment. For example: - * - * a.html: - * - * - * test.js: - * loadHTML("a.html"); - * print(x); // <- ReferenceError is thrown because x is not defined. - * - * @param {string} file_path path to the HTML file to be loaded. - */ - global.loadHTML = function(href) { - // TODO(nednguyen): Use a javascript html parser instead of relying on - // python file for parsing HTML. - // (https://github.com/google/trace-viewer/issues/1030) - var absPath = global.hrefToAbsolutePath(href); - global.loadHTMLFile(absPath, href); - }; - - global.loadScript = function(href) { - var absPath = global.hrefToAbsolutePath(href); - global.loadFile(absPath, href); - }; - - global.loadHTMLFile = function(absPath, opt_href) { - var href = opt_href || absPath; - if (loadedModulesByFilePath[absPath]) - return; - loadedModulesByFilePath[absPath] = true; - - - try { - var stripped_js = os.system('python', ['<%html2jseval-path%>', absPath]); - } catch (err) { - if (!PathUtils.exists(absPath)) - throw new Error('Error in loading ' + href + ': File does not exist'); - throw new Error('Error in loading ' + href + ': ' + err); - } - - // Add "//@ sourceURL=|file_path|" to the end of generated js to preserve - // the line numbers - stripped_js = stripped_js + '\n//@ sourceURL=' + href; - eval(stripped_js); - }; - - global.loadFile = function(absPath, opt_href) { - var href = opt_href || absPath; - var relPath = PathUtils.relPath(absPath); - try { - load(relPath); - } catch (err) { - throw new Error('Error in loading ' + href + ': ' + err); - } - }; -})(this, arguments); \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/build/d8_runner b/src/tools/google_trace_viewer/tracing/build/d8_runner deleted file mode 100755 index 9899cd12..00000000 --- a/src/tools/google_trace_viewer/tracing/build/d8_runner +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - from tracing.build import d8_runner - sys.exit(d8_runner.main()) diff --git a/src/tools/google_trace_viewer/tracing/build/d8_runner.py b/src/tools/google_trace_viewer/tracing/build/d8_runner.py deleted file mode 100755 index ce0e1581..00000000 --- a/src/tools/google_trace_viewer/tracing/build/d8_runner.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import os -import platform -import shutil -import subprocess -import StringIO -import sys -import json -import tempfile - -from tvcm import parse_html_deps - - -_V8_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), - os.path.pardir, os.path.pardir, 'tracing', 'third_party', 'v8')) - -_HTML_JS_EVAL_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), 'html2jseval.py')) - -_BOOTSTRAP_JS_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), 'd8_bootstrap.js')) - -_PATH_UTILS_JS_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), 'path_utils.js')) - -_BOOTSTRAP_JS_CONTENT = None -def _ValidateSourcePaths(source_paths): - if source_paths is None: - return - for x in source_paths: - assert os.path.exists(x) - assert os.path.isdir(x) - assert os.path.isabs(x) - -def _GetBootStrapJsContent(source_paths): - global _BOOTSTRAP_JS_CONTENT - if not _BOOTSTRAP_JS_CONTENT: - with open(_BOOTSTRAP_JS_DIR, 'r') as f: - bootstrap_js_content = f.read() - _BOOTSTRAP_JS_CONTENT = bootstrap_js_content.replace( - '<%html2jseval-path%>', _HTML_JS_EVAL_PATH) - - - bsc = _BOOTSTRAP_JS_CONTENT - - source_path_string = json.dumps(source_paths) - bsc = bsc.replace('<%source_paths%>', source_path_string) - bsc = bsc.replace('<%current_working_directory%>', os.getcwd()) - bsc = bsc.replace('<%path_utils_js_path%>', _PATH_UTILS_JS_DIR) - return bsc - - -def _IsValidJsOrHTMLFile(parser, js_file_arg): - if not os.path.exists(js_file_arg): - parser.error('The file %s does not exist' % js_file_arg) - _, extension = os.path.splitext(js_file_arg) - if extension not in ('.js', '.html'): - parser.error('Input must be a JavaScript or HTML file') - return js_file_arg - - -def _GetD8BinaryPathForPlatform(): - if platform.system() == 'Linux' and platform.machine() == 'x86_64': - return os.path.join(_V8_DIR, 'linux', 'x86_64', 'd8') - elif platform.system() == 'Darwin' and platform.machine() == 'x86_64': - return os.path.join(_V8_DIR, 'mac', 'x86_64', 'd8') - else: - raise NotImplementedError( - 'd8 binary for this platform and architecture is not yet supported') - -class RunResult(object): - def __init__(self, returncode, stdout): - self.returncode = returncode - self.stdout = stdout - -def ExecuteFile(file_path, source_paths=None, js_args=None): - """ Execute javascript program in |file_path|. - - Args: - file_path: string file_path that contains path the .js or .html file to be - executed. - source_paths: the list of absolute paths containing code. All the imports - js_args: a list of string arguments to sent to the js program. - - Returns: - The string output from running the js program. - """ - res = RunFile(file_path, source_paths, js_args) - return res.stdout - -def RunFile(file_path, source_paths=None, js_args=None): - """ Runs javascript program in |file_path|. - - Args are same as ExecuteFile. - - Returns: - A RunResult containing the program's output. - """ - assert os.path.isfile(file_path) - _ValidateSourcePaths(source_paths) - - _, extension = os.path.splitext(file_path) - if not extension in ('.html', '.js'): - raise ValueError('Can only execute .js or .html file. File %s has ' - 'unsupported file type: %s' % (file_path, extension)) - if source_paths is None: - source_paths = [os.path.dirname(file_path)] - - abs_file_path = os.path.abspath(file_path) - - try: - temp_dir = tempfile.mkdtemp() - temp_boostrap_file = os.path.join(temp_dir, '_tmp_boostrap.js') - with open(temp_boostrap_file, 'w') as f: - f.write(_GetBootStrapJsContent(source_paths)) - if extension == '.html': - f.write('\nloadHTMLFile("%s");' % abs_file_path) - else: - f.write('\nloadFile("%s");' % abs_file_path) - return _RunFileWithD8(temp_boostrap_file, js_args) - finally: - shutil.rmtree(temp_dir) - - -def ExcecuteJsString(js_string, source_paths=None, js_args=None, - original_file_name=None): - res = RunJsString(js_string, source_paths, js_args, original_file_name) - return res.stdout - -def RunJsString(js_string, source_paths=None, js_args=None, - original_file_name=None): - _ValidateSourcePaths(source_paths) - - try: - temp_dir = tempfile.mkdtemp() - if original_file_name: - name = os.path.basename(original_file_name) - name, _ = os.path.splitext(name) - temp_file = os.path.join(temp_dir, '%s.js' % name) - else: - temp_file = os.path.join(temp_dir, 'temp_program.js') - with open(temp_file, 'w') as f: - f.write(js_string) - return RunFile(temp_file, source_paths, js_args) - finally: - shutil.rmtree(temp_dir) - - -def _RunFileWithD8(js_file_path, js_args): - """ Execute the js_files with v8 engine and return the output of the program. - - Args: - js_file_path: the string path of the js file to be run. - js_args: a list of arguments to passed to the |js_file_path| program. - """ - args = [_GetD8BinaryPathForPlatform()] - args.append(os.path.abspath(js_file_path)) - full_js_args = [args[0]] - if js_args: - full_js_args += js_args - - args += ['--js_arguments'] + full_js_args - sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, err = sp.communicate() - assert err is None - - # d8 uses returncode 1 to indicate an uncaught exception, but - # _RunFileWithD8 needs to distingiush between that and quit(1). - # - # To fix this, d8_bootstrap.js monkeypatches D8's quit function to - # adds 1 to an intentioned nonzero quit. So, now, we have to undo this - # logic here in order to raise/return the right thing. - returncode = sp.returncode - if returncode == 0: - return RunResult(0, out) - elif returncode == 1: - raise RuntimeError( - "Exception raised when executing %s:\n%s" % - (js_file_path, out)) - else: - return RunResult(returncode - 1, out) - - -def main(): - parser = argparse.ArgumentParser( - description='Run javascript file with v8 engine') - parser.add_argument('file_name', help='input file', metavar='FILE', - type=lambda f: _IsValidJsOrHTMLFile(parser, f)) - parser.add_argument('--js_args', help='arguments for the js program', - nargs='+') - parser.add_argument('--source_paths', help='search path for the js program', - nargs='+', type=str) - - args = parser.parse_args() - - args.source_paths = [os.path.abspath(x) for x in args.source_paths] - res = RunFile(args.file_name, source_paths=args.source_paths, - js_args=args.js_args) - print res.stdout - return res.returncode diff --git a/src/tools/google_trace_viewer/tracing/build/d8_runner_unittest.py b/src/tools/google_trace_viewer/tracing/build/d8_runner_unittest.py deleted file mode 100755 index de5aad98..00000000 --- a/src/tools/google_trace_viewer/tracing/build/d8_runner_unittest.py +++ /dev/null @@ -1,195 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import re -import sys -import unittest - -from tracing.build import d8_runner -from tracing.build import check_common - - -class D8RunnerUnittest(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.test_data_dir = os.path.abspath( - os.path.join(os.path.dirname(__file__), 'test_data')) - - def GetTestFilePath(self, file_name): - return os.path.join(self.test_data_dir, file_name) - - def AssertHasNamedFrame(self, func_name, file_and_linum, - exception_message): - m = re.search('at %s.+\(.*%s.*\)' % (func_name, file_and_linum), - exception_message) - if not m: - sys.stderr.write('\n=============================================\n') - msg = "Expected to find %s and %s" % (func_name, file_and_linum) - sys.stderr.write('%s\n' % msg) - sys.stderr.write('=========== Begin Exception Message =========\n') - sys.stderr.write(exception_message); - sys.stderr.write('=========== End Exception Message =========\n\n') - self.assertTrue(False, msg) - - def AssertHasFrame(self, file_and_linum, - exception_message): - m = re.search('at .*%s.*' % file_and_linum, - exception_message) - if not m: - sys.stderr.write('\n=============================================\n') - msg = "Expected to find %s" % file_and_linum - sys.stderr.write('%s\n' % msg) - sys.stderr.write('=========== Begin Exception Message =========\n') - sys.stderr.write(exception_message); - sys.stderr.write('=========== End Exception Message =========\n\n') - self.assertTrue(False, msg) - - def testSimpleJsExecution(self): - file_path = self.GetTestFilePath('print_file_content.js') - dummy_test_path = self.GetTestFilePath('dummy_test_file') - output = d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir], - js_args=[dummy_test_path]) - self.assertTrue( - 'This is file contains only data for testing.\n1 2 3 4' in output) - - def testJsFileLoadHtmlFile(self): - file_path = self.GetTestFilePath('load_simple_html.js') - output = d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir]) - expected_output = ('File foo.html is loaded\n' - 'x = 1\n' - "File foo.html's second script is loaded\n" - 'x = 2\n' - 'load_simple_html.js is loaded\n') - self.assertEquals(output, expected_output) - - def testJsFileLoadJsFile(self): - file_path = self.GetTestFilePath('load_simple_js.js') - output = d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir]) - expected_output = ('bar.js is loaded\n' - 'load_simple_js.js is loaded\n') - self.assertEquals(output, expected_output) - - def testHTMLFileLoadHTMLFile(self): - file_path = self.GetTestFilePath('load_simple_html.html') - output = d8_runner.ExecuteFile( - file_path, source_paths=[self.test_data_dir]) - expected_output = ('File foo.html is loaded\n' - 'x = 1\n' - "File foo.html's second script is loaded\n" - 'x = 2\n' - 'bar.js is loaded\n' - 'File load_simple_html.html is loaded\n') - self.assertEquals(output, expected_output) - - def testQuit0Handling(self): - file_path = self.GetTestFilePath('quit_0_test.js') - res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir]) - self.assertEquals(res.returncode, 0) - - def testQuit1Handling(self): - file_path = self.GetTestFilePath('quit_1_test.js') - res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir]) - self.assertEquals(res.returncode, 1) - - def testQuit1Handling(self): - file_path = self.GetTestFilePath('quit_42_test.js') - res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir]) - self.assertEquals(res.returncode, 42) - - def testQuit274Handling(self): - file_path = self.GetTestFilePath('quit_274_test.js') - res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir]) - self.assertEquals(res.returncode, 238) - - def testErrorStackTraceJs(self): - file_path = self.GetTestFilePath('error_stack_test.js') - # error_stack_test.js imports load_simple_html.html - # load_simple_html.html imports foo.html - # foo.html imports error.js - # error.js defines maybeRaiseException() method that can raise exception - # foo.html defines maybeRaiseExceptionInFoo() method that calls - # maybeRaiseException() - # Finally, we call maybeRaiseExceptionInFoo() error_stack_test.js - # Exception log should capture these method calls' stack trace. - with self.assertRaises(RuntimeError) as context: - d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir]) - - # Assert error stack trace contain src files' info. - exception_message = context.exception.message - self.assertIn( - ('error.js:7: Error: Throw ERROR\n' - " throw new Error('Throw ERROR');"), exception_message) - self.AssertHasNamedFrame('maybeRaiseException', 'error.js:7', - exception_message) - self.AssertHasNamedFrame('global.maybeRaiseExceptionInFoo', 'foo.html:13', - exception_message) - self.AssertHasFrame('error_stack_test.js:14', exception_message) - def testErrorStackTraceHTML(self): - file_path = self.GetTestFilePath('error_stack_test.html') - # error_stack_test.html imports error_stack_test.js - # error_stack_test.js imports load_simple_html.html - # load_simple_html.html imports foo.html - # foo.html imports error.js - # error.js defines maybeRaiseException() method that can raise exception - # foo.html defines maybeRaiseExceptionInFoo() method that calls - # maybeRaiseException() - # Finally, we call maybeRaiseExceptionInFoo() error_stack_test.js - # Exception log should capture these method calls' stack trace. - with self.assertRaises(RuntimeError) as context: - d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir]) - - # Assert error stack trace contain src files' info. - exception_message = context.exception.message - self.assertIn( - ('error.js:7: Error: Throw ERROR\n' - " throw new Error('Throw ERROR');"), exception_message) - - self.AssertHasNamedFrame('maybeRaiseException', 'error.js:7', - exception_message) - self.AssertHasNamedFrame('global.maybeRaiseExceptionInFoo', 'foo.html:13', - exception_message) - self.AssertHasFrame('error_stack_test.js:14', exception_message) - self.AssertHasNamedFrame('eval', 'error_stack_test.html:5', - exception_message) - - def testStackTraceOfErroWhenLoadingHTML(self): - file_path = self.GetTestFilePath('load_error.html') - with self.assertRaises(RuntimeError) as context: - d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir]) - - # Assert error stack trace contain src files' info. - exception_message = context.exception.message - - self.assertIn('Error: /does_not_exist.html not found', exception_message) - self.AssertHasNamedFrame('eval', 'load_error_2.html:6', exception_message) - self.AssertHasNamedFrame('eval', 'load_error.html:1', exception_message) - - def testStackTraceOfErroWhenLoadingJS(self): - file_path = self.GetTestFilePath('load_js_error.html') - with self.assertRaises(RuntimeError) as context: - d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir]) - - # Assert error stack trace contain src files' info. - exception_message = context.exception.message - - self.assertIn('Error: /does_not_exist.js not found', exception_message) - self.AssertHasNamedFrame('eval', 'load_js_error_2.html:5', - exception_message) - self.AssertHasNamedFrame('eval', 'load_js_error.html:1', - exception_message) - - def testConsolePolyfill(self): - self.assertEquals( - d8_runner.ExcecuteJsString('console.log("hello", "world");'), - 'hello world\n') - self.assertEquals( - d8_runner.ExcecuteJsString('console.info("hello", "world");'), - 'Info: hello world\n') - self.assertEquals( - d8_runner.ExcecuteJsString('console.warn("hello", "world");'), - 'Warning: hello world\n') - self.assertEquals( - d8_runner.ExcecuteJsString('console.error("hello", "world");'), - 'Error: hello world\n') diff --git a/src/tools/google_trace_viewer/tracing/build/fixjsstyle b/src/tools/google_trace_viewer/tracing/build/fixjsstyle deleted file mode 100755 index 36bc61b5..00000000 --- a/src/tools/google_trace_viewer/tracing/build/fixjsstyle +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - from tracing.build import fixjsstyle - sys.exit(fixjsstyle.main()) diff --git a/src/tools/google_trace_viewer/tracing/build/fixjsstyle.py b/src/tools/google_trace_viewer/tracing/build/fixjsstyle.py deleted file mode 100755 index 5465673e..00000000 --- a/src/tools/google_trace_viewer/tracing/build/fixjsstyle.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os -import sys - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project - -def main(): - project = tracing_project.TracingProject() - - sys.path.append(os.path.join( - project.tracing_third_party_path, 'python_gflags')) - sys.path.append(os.path.join( - project.tracing_third_party_path, 'closure_linter')) - - from closure_linter import fixjsstyle - - os.chdir(project.tracing_src_path) - - fixjsstyle.main() diff --git a/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents b/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents deleted file mode 100755 index 0949a335..00000000 --- a/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - from tracing.build import generate_about_tracing_contents - sys.exit(generate_about_tracing_contents.main(sys.argv)) diff --git a/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents.py b/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents.py deleted file mode 100755 index 280d3310..00000000 --- a/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import codecs -import optparse -import os -import sys - -import tvcm - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project - -def main(args): - parser = optparse.OptionParser(usage="%prog --outdir=") - parser.add_option("--outdir", dest="out_dir", - help="Where to place generated content") - parser.add_option('--no-min', dest='no_min', default=False, - action='store_true', - help='skip minification') - options, args = parser.parse_args(args) - - if not options.out_dir: - sys.stderr.write("ERROR: Must specify --outdir=") - parser.print_help() - return 1 - - filenames = ["ui/extras/about_tracing/about_tracing.html"] - project = tracing_project.TracingProject() - load_sequence = project.CalcLoadSequenceForModuleFilenames(filenames) - - olddir = os.getcwd() - try: - if not os.path.exists(options.out_dir): - os.makedirs(options.out_dir) - o = codecs.open(os.path.join(options.out_dir, "about_tracing.html"), 'w', - encoding='utf-8') - try: - tvcm.GenerateStandaloneHTMLToFile( - o, - load_sequence, - title='chrome://tracing', - flattened_js_url='tracing.js', - minify=not options.no_min) - except tvcm.module.DepsException, ex: - sys.stderr.write("Error: %s\n\n" % str(ex)) - return 255 - o.close() - - - o = codecs.open(os.path.join(options.out_dir, "about_tracing.js"), 'w', - encoding='utf-8') - assert o.encoding == 'utf-8' - tvcm.GenerateJSToFile( - o, - load_sequence, - use_include_tags_for_scripts=False, - dir_for_include_tag_root=options.out_dir, - minify=not options.no_min) - o.close() - - finally: - os.chdir(olddir) - - return 0 diff --git a/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents_unittest.py b/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents_unittest.py deleted file mode 100755 index acb0d6fd..00000000 --- a/src/tools/google_trace_viewer/tracing/build/generate_about_tracing_contents_unittest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import base64 -import os -import unittest -import tempfile -import shutil -import sys - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing.build import generate_about_tracing_contents - -class GenerateAboutTracingContentsUnittTest(unittest.TestCase): - def test_smokeTest(self): - try: - tmpdir = tempfile.mkdtemp() - res = generate_about_tracing_contents.main(['--outdir', tmpdir]) - assert res == 0 - finally: - shutil.rmtree(tmpdir) diff --git a/src/tools/google_trace_viewer/tracing/build/gjslint b/src/tools/google_trace_viewer/tracing/build/gjslint deleted file mode 100755 index 617b475c..00000000 --- a/src/tools/google_trace_viewer/tracing/build/gjslint +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -src_dir = os.path.join(os.path.dirname(__file__), '..') - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - import tracing - from hooks import gjslint - sys.exit(gjslint.Main([ - os.path.join(top_dir, 'tracing', 'tracing'), - ])) diff --git a/src/tools/google_trace_viewer/tracing/build/gjslint.py b/src/tools/google_trace_viewer/tracing/build/gjslint.py deleted file mode 100755 index 4ef9d791..00000000 --- a/src/tools/google_trace_viewer/tracing/build/gjslint.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os -import sys - -from tracing import tracing_project - -def Main(paths_to_lint): - project = tracing_project.TracingProject() - new_paths = [ - os.path.abspath(os.path.join( - project.tracing_third_party_path, 'python_gflags')), - os.path.abspath(os.path.join( - project.tracing_third_party_path, 'closure_linter')) - ] - sys.path += new_paths - try: - _MainImpl(paths_to_lint) - finally: - for p in new_paths: - sys.path.remove(p) - -def _MainImpl(paths_to_lint): - from closure_linter import gjslint - - if sys.argv[1:] == ['--help']: - sys.exit(gjslint.main()) - - if len(sys.argv) > 1: - sys.stderr.write('No arguments allowed') - sys.exit(1) - - sys.argv.append('--strict') - sys.argv.append('--unix_mode') - sys.argv.append('--check_html') - for p in paths_to_lint: - sys.argv.extend(['-r', os.path.relpath(p)]) - - gjslint.main() diff --git a/src/tools/google_trace_viewer/tracing/build/html2jseval.py b/src/tools/google_trace_viewer/tracing/build/html2jseval.py deleted file mode 100755 index c38a7343..00000000 --- a/src/tools/google_trace_viewer/tracing/build/html2jseval.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) -sys.path.append(top_dir) - -from tracing import tracing_project - -from tvcm import parse_html_deps - -def Main(args): - file_name = args[0] - with open(file_name, 'r') as f: - contents = f.read() - res = parse_html_deps.HTMLModuleParser().Parse(contents) - print res.GenerateJSForHeadlessImport() - -if __name__ == '__main__': - sys.exit(Main(sys.argv[1:])) diff --git a/src/tools/google_trace_viewer/tracing/build/js_checks.py b/src/tools/google_trace_viewer/tracing/build/js_checks.py deleted file mode 100755 index 0803c162..00000000 --- a/src/tools/google_trace_viewer/tracing/build/js_checks.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import os -import sys -import re - -class JSChecker(object): - def __init__(self, input_api, file_filter=None): - self.input_api = input_api - if file_filter: - self.file_filter = file_filter - else: - self.file_filter = lambda x: True - - def RegexCheck(self, line_number, line, regex, message): - """Searches for |regex| in |line| to check for a particular style - violation, returning a message like the one below if the regex matches. - The |regex| must have exactly one capturing group so that the relevant - part of |line| can be highlighted. If more groups are needed, use - "(?:...)" to make a non-capturing group. Sample message: - - line 6: Use var instead of const. - const foo = bar(); - ^^^^^ - """ - match = re.search(regex, line) - if match: - assert len(match.groups()) == 1 - start = match.start(1) - length = match.end(1) - start - return ' line %d: %s\n%s\n%s' % ( - line_number, - message, - line, - self.error_highlight(start, length)) - return '' - - def ConstCheck(self, i, line): - """Check for use of the 'const' keyword.""" - if re.search(r'\*\s+@const', line): - # Probably a JsDoc line - return '' - - return self.RegexCheck(i, line, r'(?:^|\s|\()(const)\s', - 'Use var instead of const.') - - def error_highlight(self, start, length): - """Takes a start position and a length, and produces a row of '^'s to - highlight the corresponding part of a string. - """ - return start * ' ' + length * '^' - - def _makeErrorOrWarning(self, error_text, filename): - return error_text - - def RunChecks(self): - """Check for violations of the Chromium JavaScript style guide. See - http://chromium.org/developers/web-development-style-guide#TOC-JavaScript - """ - - import sys - import warnings - old_path = sys.path - old_filters = warnings.filters - - try: - base_path = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..')) - closure_linter_path = os.path.join( - base_path, 'tracing', 'third_party', 'closure_linter') - gflags_path = os.path.join( - base_path, 'tracing', 'third_party', 'python_gflags') - sys.path.insert(0, closure_linter_path) - sys.path.insert(0, gflags_path) - - warnings.filterwarnings('ignore', category=DeprecationWarning) - - from closure_linter import checker, errors - from closure_linter.common import errorhandler - - finally: - sys.path = old_path - warnings.filters = old_filters - - class ErrorHandlerImpl(errorhandler.ErrorHandler): - """Filters out errors that don't apply to Chromium JavaScript code.""" - - def __init__(self): - self._errors = [] - - def HandleFile(self, filename, first_token): - self._filename = filename - - def HandleError(self, error): - if (self._valid(error)): - error.filename = self._filename - self._errors.append(error) - - def GetErrors(self): - return self._errors - - def HasErrors(self): - return bool(self._errors) - - def _valid(self, error): - """Check whether an error is valid. Most errors are valid, with a few - exceptions which are listed here. - """ - - is_grit_statement = bool( - re.search(" - - - - - - - - - -
-
- - - \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/build/run_dev_server_tests b/src/tools/google_trace_viewer/tracing/build/run_dev_server_tests deleted file mode 100755 index 1c76b2e1..00000000 --- a/src/tools/google_trace_viewer/tracing/build/run_dev_server_tests +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os -import shutil -import stat -import subprocess -import sys -import tempfile -import time -import urllib2 -import zipfile - -# URL on omahaproxy.appspot.com which lists cloud storage buckets. -OMAHA_URL = 'https://omahaproxy.appspot.com/all?os=%s&channel=stable' - -# URL in cloud storage to download Chrome zip from. -CLOUDSTORAGE_URL = ('https://commondatastorage.googleapis.com/chrome-unsigned' - '/desktop-W15K3Y/%s/%s/chrome-%s.zip') - -# Mapping of sys.platform -> platform-specific names and paths. -PLATFORM_MAPPING = { - 'linux2': { - 'omaha': 'linux', - 'gs': 'precise64', - 'chromepath': 'chrome-precise64/chrome', - }, - 'win32': { - 'omaha': 'win', - 'gs': 'win', - 'chromepath': 'chrome-win\\chrome.exe', - }, - 'darwin': { - 'omaha': 'mac', - 'gs': 'mac', - 'chromepath': 'chrome-mac/Google Chrome.app/Contents', - }, -} - -def DownloadChromeStable(): - omaha_platform = PLATFORM_MAPPING[sys.platform]['omaha'] - omaha_url = OMAHA_URL % omaha_platform - response = urllib2.urlopen(omaha_url) - bucket = response.readlines()[1].split(',')[2] - cs_dir = PLATFORM_MAPPING[sys.platform]['gs'] - cs_url = CLOUDSTORAGE_URL % (bucket, cs_dir, cs_dir) - tmpdir = tempfile.mkdtemp() - zip_path = os.path.join(tmpdir, 'chrome.zip') - with open(zip_path, 'wb') as local_file: - local_file.write(urllib2.urlopen(cs_url).read()) - zf = zipfile.ZipFile(zip_path) - zf.extractall(path=tmpdir) - return tmpdir - - -def main(): - tmpdir = DownloadChromeStable() - server_path = os.path.join(os.path.dirname( - os.path.abspath(__file__)), os.pardir, os.pardir, 'run_dev_server') - server_process = subprocess.Popen( - [server_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - time.sleep(5) - - chrome_path = os.path.join( - tmpdir, PLATFORM_MAPPING[sys.platform]['chromepath']) - os.chmod(chrome_path, os.stat(chrome_path).st_mode | stat.S_IEXEC) - chrome_command = [ - chrome_path, - '--no-sandbox', - '--no-experiments', - '--no-first-run', - '--noerrdialogs', - 'http://localhost:8003/base/tests.html?headless=true&testTypeToRun=all', - ] - chrome_process = subprocess.Popen( - chrome_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - server_out, server_err = server_process.communicate() - chrome_process.kill() - shutil.rmtree(tmpdir) - if server_process.returncode != 0: - logging.error('Tests failed!') - logging.error('Server stderr:') - logging.error(server_err) - logging.error('Server stdout:') - logging.error(server_out) - else: - print server_out - sys.exit(server_process.returncode) - - - -if __name__ == "__main__": - main() diff --git a/src/tools/google_trace_viewer/tracing/build/trace2html.py b/src/tools/google_trace_viewer/tracing/build/trace2html.py deleted file mode 100755 index 8ce5097f..00000000 --- a/src/tools/google_trace_viewer/tracing/build/trace2html.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import codecs -import base64 -import gzip -import json -import optparse -import shutil -import os -import StringIO -import sys -import tempfile - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project -from tvcm import generate - -def Main(args): - parser = optparse.OptionParser( - usage="%prog trace_file1 [trace_file2 ...]", - epilog="""Takes the provided trace file and produces a standalone html -file that contains both the trace and the trace viewer.""") - - project = tracing_project.TracingProject() - project.AddConfigNameOptionToParser(parser) - - parser.add_option( - "--output", dest="output", - help='Where to put the generated result. If not ' + - 'given, the trace filename is used, with an html suffix.') - parser.add_option( - "--quiet", action='store_true', - help='Dont print the output file name') - options, args = parser.parse_args(args) - if len(args) == 0: - parser.error('At least one trace file required') - - if options.output: - output_filename = options.output - elif len(args) > 1: - parser.error('Must specify --output if >1 trace file') - else: - namepart = os.path.splitext(args[0])[0] - output_filename = namepart + '.html' - - with codecs.open(output_filename, mode='w', encoding='utf-8') as f: - WriteHTMLForTracesToFile(args, f, config_name=options.config_name) - - if not options.quiet: - print output_filename - return 0 - - -class ViewerDataScript(generate.ExtraScript): - def __init__(self, trace_data_string, mime_type): - super(ViewerDataScript, self).__init__() - self._trace_data_string = trace_data_string - self._mime_type = mime_type - - def WriteToFile(self, output_file): - output_file.write('\n') - - -def WriteHTMLForTraceDataToFile(trace_data_list, - title, output_file, - config_name=None): - project = tracing_project.TracingProject() - - if config_name == None: - config_name = project.GetDefaultConfigName() - - modules = [ - 'trace2html', - 'extras.importer.gzip_importer', # Must have this regardless of config. - project.GetModuleNameForConfigName(config_name) - ] - - load_sequence = project.CalcLoadSequenceForModuleNames(modules) - - scripts = [] - for trace_data in trace_data_list: - # If the object was previously decoded from valid JSON data (e.g., in - # WriteHTMLForTracesToFile), it will be a JSON object at this point and we - # should re-serialize it into a string. Other types of data will be already - # be strings. - if not isinstance(trace_data, basestring): - trace_data = json.dumps(trace_data) - mime_type = 'application/json' - else: - mime_type = 'text/plain' - scripts.append(ViewerDataScript(trace_data, mime_type)) - generate.GenerateStandaloneHTMLToFile( - output_file, load_sequence, title, extra_scripts=scripts) - - -def WriteHTMLForTracesToFile(trace_filenames, output_file, config_name=None): - trace_data_list = [] - for filename in trace_filenames: - with open(filename, 'r') as f: - trace_data = f.read() - try: - trace_data = json.loads(trace_data) - except ValueError: - pass - trace_data_list.append(trace_data) - - title = "Trace from %s" % ','.join(trace_filenames) - WriteHTMLForTraceDataToFile(trace_data_list, title, output_file, config_name) diff --git a/src/tools/google_trace_viewer/tracing/build/trace2html_unittest.py b/src/tools/google_trace_viewer/tracing/build/trace2html_unittest.py deleted file mode 100755 index 29e87200..00000000 --- a/src/tools/google_trace_viewer/tracing/build/trace2html_unittest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import codecs -import unittest -import tempfile -import os - -from tracing.build import trace2html - -class Trace2HTMLTests(unittest.TestCase): - def test_writeHTMLForTracesToFile(self): - with tempfile.NamedTemporaryFile(mode='w', suffix='.html') as raw_tmpfile: - with codecs.open(raw_tmpfile.name, 'w', encoding='utf-8') as tmpfile: - simple_trace_path = os.path.join( - os.path.dirname(__file__), - '..', 'test_data', 'simple_trace.json') - big_trace_path = os.path.join( - os.path.dirname(__file__), - '..', 'test_data', 'big_trace.json') - non_json_trace_path = os.path.join( - os.path.dirname(__file__), - '..', 'test_data', 'android_systrace.txt') - res = trace2html.WriteHTMLForTracesToFile( - [big_trace_path, simple_trace_path, non_json_trace_path], tmpfile) diff --git a/src/tools/google_trace_viewer/tracing/build/tracing_dev_server.py b/src/tools/google_trace_viewer/tracing/build/tracing_dev_server.py deleted file mode 100755 index e3b04caa..00000000 --- a/src/tools/google_trace_viewer/tracing/build/tracing_dev_server.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import json -import os -import sys - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project -import tvcm - -def getFilesIn(basedir): - data_files = [] - for dirpath, dirnames, filenames in os.walk(basedir, followlinks=True): - new_dirnames = [d for d in dirnames if not d.startswith('.')] - del dirnames[:] - dirnames += new_dirnames - - for f in filenames: - if f.startswith('.'): - continue - if f == 'README.md': - continue - full_f = os.path.join(dirpath, f) - rel_f = os.path.relpath(full_f, basedir) - data_files.append(rel_f) - - data_files.sort() - return data_files - -def do_GET_json_examples(request): - data_files = getFilesIn(request.server.data_dir) - files_as_json = json.dumps(data_files) - - request.send_response(200) - request.send_header('Content-Type', 'application/json') - request.send_header('Content-Length', len(files_as_json)) - request.end_headers() - request.wfile.write(files_as_json) - -def do_GET_json_examples_skp(request): - data_files = getFilesIn(request.server.skp_data_dir) - files_as_json = json.dumps(data_files) - - request.send_response(200) - request.send_header('Content-Type', 'application/json') - request.send_header('Content-Length', len(files_as_json)) - request.end_headers() - request.wfile.write(files_as_json) - -def do_GET_json_tests(self): - test_module_resources = self.server.project.FindAllTestModuleResources() - - test_relpaths = [x.unix_style_relative_path - for x in test_module_resources] - - tests = {'test_relpaths': test_relpaths} - tests_as_json = json.dumps(tests); - - self.send_response(200) - self.send_header('Content-Type', 'application/json') - self.send_header('Content-Length', len(tests_as_json)) - self.end_headers() - self.wfile.write(tests_as_json) - -def do_POST_report_test_results(request): - request.send_response(200) - request.send_header('Content-Length', '0') - request.end_headers() - msg = request.rfile.read() - ostream = sys.stdout if 'PASSED' in msg else sys.stderr - ostream.write(msg + '\n') - -def do_POST_report_test_completion(request): - request.send_response(200) - request.send_header('Content-Length', '0') - request.end_headers() - msg = request.rfile.read() - sys.stdout.write(msg + '\n') - request.server.RequestShutdown(exit_code=(0 if 'ALL_PASSED' in msg else 1)) - -def Main(args): - project = tracing_project.TracingProject() - - parser = argparse.ArgumentParser(description='Run tracing development server') - parser.add_argument( - '-d', '--data-dir', - default=os.path.abspath(os.path.join(project.test_data_path))) - parser.add_argument( - '-s', '--skp-data-dir', - default=os.path.abspath(os.path.join(project.skp_data_path))) - parser.add_argument('-p', '--port', default=8003, type=int) - args = parser.parse_args() - - server = tvcm.DevServer(port=args.port, project=project) - server.data_dir = os.path.abspath(args.data_dir) - server.skp_data_dir = os.path.abspath(args.skp_data_dir) - project.source_paths.append(server.data_dir) - - server.AddPathHandler('/json/examples', do_GET_json_examples) - server.AddPathHandler('/tr/json/tests', do_GET_json_tests) - server.AddPathHandler('/json/examples/skp', do_GET_json_examples_skp) - - server.AddSourcePathMapping(project.tracing_root_path) - - server.AddPathHandler('/test_automation/notify_test_result', - do_POST_report_test_results, supports_post=True) - server.AddPathHandler('/test_automation/notify_completion', - do_POST_report_test_completion, supports_post=True) - - - server.serve_forever() diff --git a/src/tools/google_trace_viewer/tracing/build/update_gypi b/src/tools/google_trace_viewer/tracing/build/update_gypi deleted file mode 100755 index c515da6c..00000000 --- a/src/tools/google_trace_viewer/tracing/build/update_gypi +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -if __name__ == '__main__': - top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) - sys.path.append(top_dir) - from tracing import tracing_project - from tracing.build import update_gypi - sys.exit(update_gypi.Update()) diff --git a/src/tools/google_trace_viewer/tracing/build/update_gypi.py b/src/tools/google_trace_viewer/tracing/build/update_gypi.py deleted file mode 100755 index 43e38adf..00000000 --- a/src/tools/google_trace_viewer/tracing/build/update_gypi.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import collections -import os -import re -import sys - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing.build import check_common -from tracing import tracing_project - -class _Token(object): - def __init__(self, data, id=None): - self.data = data - if id: - self.id = id - else: - self.id = 'plain' - - -class BuildFile(object): - def __init__(self, text, file_groups): - self._file_groups = file_groups - self._tokens = [token for token in self._Tokenize(text)] - - def _Tokenize(self, text): - rest = text - token_regex = self._TokenRegex() - while len(rest): - m = token_regex.search(rest) - if not m: - # In `rest', we couldn't find a match. - # So, lump the entire `rest' into a token - # and stop producing any more tokens. - yield _Token(rest) - return - min_index, end_index, matched_token = self._ProcessMatch(m) - - if min_index > 0: - yield _Token(rest[:min_index]) - - yield matched_token - rest = rest[end_index:] - - def Update(self, files_by_group): - for token in self._tokens: - if token.id in files_by_group: - token.data = self._GetReplacementListAsString( - token.data, - files_by_group[token.id] - ) - - def Write(self, f): - for token in self._tokens: - f.write(token.data) - - def _ProcessMatch(self, match): - raise Exception("Not implemented.") - - def _TokenRegex(self): - raise Exception("Not implemented.") - - def _GetReplacementListAsString(self, existing_list_as_string, filelist): - raise Exception("Not implemented.") - - -class GypiFile(BuildFile): - def _ProcessMatch(self, match): - min_index = match.start(2) - end_index = match.end(2) - token = _Token(match.string[min_index:end_index], - id=match.groups()[0]) - return min_index, end_index, token - - def _TokenRegex(self): - # regexp to match the following: - # 'file_group_name': [ - # 'path/to/one/file.extension', - # 'another/file.ex', - # ] - # In the match, - # group 1 is : 'file_group_name' - # group 2 is : """ 'path/to/one/file.extension',\n 'another/file.ex',\n""" - regexp_str = "'(%s)': \[\n(.+?) +\],?\n" % "|".join(self._file_groups) - return re.compile(regexp_str, re.MULTILINE | re.DOTALL) - - def _GetReplacementListAsString(self, existing_list_as_string, filelist): - list_entry = existing_list_as_string.splitlines()[0] - prefix, entry, suffix = list_entry.split("'") - return "".join(["'".join([prefix, filename, suffix + '\n']) - for filename in filelist]) - - -def _GroupFiles(fileNameToGroupNameFunc, filenames): - file_groups = collections.defaultdict(lambda: []) - for filename in filenames: - file_groups[fileNameToGroupNameFunc(filename)].append(filename) - for group in file_groups: - file_groups[group].sort() - return file_groups - - -def _UpdateBuildFile(filename, build_file_class): - updated_content = None - with open(filename, 'r') as f: - build_file = build_file_class(f.read(), check_common.FILE_GROUPS) - files_by_group = _GroupFiles(check_common.GetFileGroupFromFileName, - check_common.GetKnownFiles()) - build_file.Update(files_by_group) - with open(filename, 'w') as f: - build_file.Write(f) - - -def UpdateGypi(): - tvp = tracing_project.TracingProject() - _UpdateBuildFile( - os.path.join(tvp.tracing_root_path, 'trace_viewer.gypi'), GypiFile) - - -def Update(): - UpdateGypi() diff --git a/src/tools/google_trace_viewer/tracing/build/update_gypi_unittest.py b/src/tools/google_trace_viewer/tracing/build/update_gypi_unittest.py deleted file mode 100755 index 7f793f52..00000000 --- a/src/tools/google_trace_viewer/tracing/build/update_gypi_unittest.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import unittest -import StringIO - -from tracing.build.update_gypi import BuildFile, GypiFile - -class UpdateGypiTests(unittest.TestCase): - def setUp(self): - self.file_groups = ['group1', 'group2'] - - def test_GypiTokenizer(self): - content = """useless data -'group1': [ - - ] -Note the four spaces bofer the ] above""" - gypi_file = GypiFile(content, self.file_groups) - try: - assert len(gypi_files._tokens) == 3 - assert gypi_files._tokens[0].id == 'plain' - assert gypi_files._tokens[0].data == """useless data -'group1': [ -""" - assert gypi_files._tokens[1].id == 'group1' - assert gypi_files._tokens[1].data == """ -""" - assert gypi_files._tokens[2].id == 'plain' - assert gypi_files._tokens[2].data == """ ] -Note the four spaces before the ] above """ - except: - pass - - def test_GypiFileListBuilder(self): - gypi_file = GypiFile("", self.file_groups) - existing_list = """ '/four/spaces/indent', - '/five/spaces/but/only/first/line/matters', -""" - new_list = ['item1', 'item2', 'item3'] - try: - assert (gypi_file._GetReplacementListAsString(existing_list, new_list) - == - """ 'item1',\n 'item2',\n 'item3',\n""") - except: - pass diff --git a/src/tools/google_trace_viewer/tracing/build/vulcanize_trace_viewer.py b/src/tools/google_trace_viewer/tracing/build/vulcanize_trace_viewer.py deleted file mode 100755 index 9fbb37c9..00000000 --- a/src/tools/google_trace_viewer/tracing/build/vulcanize_trace_viewer.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import codecs -import optparse -import os -import StringIO -import sys -import tempfile - -tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..')) -if tracing_path not in sys.path: - sys.path.append(tracing_path) - -from tracing import tracing_project -from tvcm import generate - -def Main(args): - - parser = optparse.OptionParser( - usage="%prog ", - epilog="""Produces a standalone html import that contains the -trace viewer.""") - - project = tracing_project.TracingProject() - project.AddConfigNameOptionToParser(parser) - - parser.add_option('--no-min', dest='no_min', default=False, - action='store_true', - help='skip minification') - parser.add_option('--report-sizes', dest='report_sizes', default=False, - action='store_true', - help='Explain what makes tracing big.') - parser.add_option('--report-deps', dest='report_deps', default=False, - action='store_true', - help='Print a dot-formatted deps graph.') - parser.add_option( - "--output", dest="output", - help='Where to put the generated result. If not ' + - 'given, $TRACING/tracing/bin/trace_viewer.html is used.') - - options, args = parser.parse_args(args) - if len(args) != 0: - parser.error('No arguments needed.') - - tracing_dir = os.path.relpath( - os.path.join(os.path.dirname(__file__), '..', '..')) - if options.output: - output_filename = options.output - else: - output_filename = os.path.join( - tracing_dir, 'tracing/bin/trace_viewer_%s.html' % options.config_name) - - with codecs.open(output_filename, 'w', encoding='utf-8') as f: - WriteTraceViewer( - f, - config_name=options.config_name, - minify=not options.no_min, - report_sizes=options.report_sizes, - report_deps=options.report_deps) - - return 0 - - -def WriteTraceViewer(output_file, - config_name=None, - minify=False, - report_sizes=False, - report_deps=False, - output_html_head_and_body=True, - extra_search_paths=None, - extra_module_names_to_load=None): - project = tracing_project.TracingProject() - if extra_search_paths: - for p in extra_search_paths: - project.source_paths.append(p) - if config_name == None: - config_name = project.GetDefaultConfigName() - - module_names = ['trace_viewer', - project.GetModuleNameForConfigName(config_name)] - if extra_module_names_to_load: - module_names += extra_module_names_to_load - load_sequence = project.CalcLoadSequenceForModuleNames( - module_names) - - if report_deps: - sys.stdout.write(project.GetDepsGraphFromModuleNames(module_names)) - - generate.GenerateStandaloneHTMLToFile( - output_file, load_sequence, - minify=minify, report_sizes=report_sizes, - output_html_head_and_body=output_html_head_and_body) diff --git a/src/tools/google_trace_viewer/tracing/build/vulcanize_trace_viewer_unittest.py b/src/tools/google_trace_viewer/tracing/build/vulcanize_trace_viewer_unittest.py deleted file mode 100755 index d3b60f61..00000000 --- a/src/tools/google_trace_viewer/tracing/build/vulcanize_trace_viewer_unittest.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import codecs -import unittest -import tempfile -import os - -from tracing.build import vulcanize_trace_viewer -from tvcm import generate - -class Trace2HTMLTests(unittest.TestCase): - def test_writeHTMLForTracesToFile(self): - with tempfile.NamedTemporaryFile(mode='w', suffix='.html') as raw_tmpfile: - with codecs.open(raw_tmpfile.name, 'w', encoding='utf-8') as tmpfile: - res = vulcanize_trace_viewer.WriteTraceViewer(tmpfile) diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-blue.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-blue.png deleted file mode 100755 index 0eb12eca..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-blue.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-green.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-green.png deleted file mode 100755 index e6ba7610..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-green.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-red.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-red.png deleted file mode 100755 index 915d7064..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-red.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-yellow.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-yellow.png deleted file mode 100755 index a805cc1b..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-circle-yellow.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-blue.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-blue.png deleted file mode 100755 index 441f684b..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-blue.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-green.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-green.png deleted file mode 100755 index a4da2ef0..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-green.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-red.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-red.png deleted file mode 100755 index fc8e7fe7..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-red.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-yellow.png b/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-yellow.png deleted file mode 100755 index 7216975b..00000000 Binary files a/src/tools/google_trace_viewer/tracing/images/trace-viewer-square-yellow.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/run_d8_tests b/src/tools/google_trace_viewer/tracing/run_d8_tests deleted file mode 100755 index 3edd2cb0..00000000 --- a/src/tools/google_trace_viewer/tracing/run_d8_tests +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys -import os - -hooks_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) -if hooks_path not in sys.path: - sys.path.append(hooks_path) - -from hooks import install - - -from tracing import tracing_project -from tracing.build import d8_runner - - -def Main(args): - project = tracing_project.TracingProject() - d8_test_module_resources = project.FindAllD8TestModuleResources() - d8_test_module_filenames = [x.unix_style_relative_path - for x in d8_test_module_resources] - d8_test_module_filenames.sort() - - cmd = """ - loadHTML('/base/d8_tests.html'); - """ - res = d8_runner.RunJsString(cmd, - source_paths=list(project.source_paths), - js_args=d8_test_module_filenames) - print res.stdout - return res.returncode - -if __name__ == '__main__': - install.InstallHooks() - - sys.exit(Main(sys.argv[1:])) \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/run_dev_server b/src/tools/google_trace_viewer/tracing/run_dev_server deleted file mode 100755 index ecae4215..00000000 --- a/src/tools/google_trace_viewer/tracing/run_dev_server +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -hooks_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) -if hooks_path not in sys.path: - sys.path.append(hooks_path) - -from hooks import install -from tracing.build import tracing_dev_server - -if __name__ == '__main__': - install.InstallHooks() - sys.exit(tracing_dev_server.Main(sys.argv[1:])) diff --git a/src/tools/google_trace_viewer/tracing/run_py_tests b/src/tools/google_trace_viewer/tracing/run_py_tests deleted file mode 100755 index af0a31d1..00000000 --- a/src/tools/google_trace_viewer/tracing/run_py_tests +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys -import os - -hooks_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) -if hooks_path not in sys.path: - sys.path.append(hooks_path) - -from hooks import install - -import tracing # Brings in tvcm bindings. -from tvcm import test_runner -import tvcm - - -if __name__ == '__main__': - install.InstallHooks() - - runner = test_runner.TestRunner() - runner.AddModule(tvcm) - runner.AddModule(tracing) - sys.exit(runner.Main()) diff --git a/src/tools/google_trace_viewer/tracing/run_tests b/src/tools/google_trace_viewer/tracing/run_tests deleted file mode 100755 index fd6887f6..00000000 --- a/src/tools/google_trace_viewer/tracing/run_tests +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import logging -import os -import subprocess -import sys - - -_RUN_PY_TESTS_DIR = os.path.join(os.path.dirname(__file__), 'run_py_tests') -_RUN_D8_TESTS_DIR = os.path.join(os.path.dirname(__file__), 'run_d8_tests') -_RUN_DEV_SERVER_DIR = os.path.join(os.path.dirname(__file__), 'run_dev_server') - - -class bcolors(object): - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - - -def _RunPyTests(): - return subprocess.call([_RUN_PY_TESTS_DIR]) - - -def _RunD8Tests(): - return subprocess.call([_RUN_D8_TESTS_DIR]) - - -def _RunDevServer(chrome_command): - if (sys.platform.startswith('linux') and os.getenv('DISPLAY') is None): - logging.warning( - 'Browser found but cannot run browser tests because you do not have a ' - 'DISPLAY environment set.') - return 0 - args = [ - chrome_command, '--no-sandbox', '--no-experiments', '--no-first-run', - '--noerrdialogs', - 'http://localhost:8003/base/tests.html?headless=true&testTypeToRun=all'] - chrome_proc = subprocess.Popen(args) - exit_code = subprocess.call([_RUN_DEV_SERVER_DIR]) - chrome_proc.terminate() - if chrome_proc.poll() is None: - chrome_proc.kill() - return exit_code - - -def _TryGettingChromeCommand(): - if sys.platform.startswith('darwin'): # Mac - chrome_path = ( - '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome') - if os.path.isfile(chrome_path): - return chrome_path - elif sys.platform.startswith('linux'): - found = False - try: - with open(os.devnull, 'w') as devnull: - found = subprocess.call(['google-chrome', '--version'], - stdout=devnull, stderr=devnull) == 0 - except OSError: - pass - if found: - return 'google-chrome' - # TODO(nedn): Find the default path to chrome on win platform. - return None - - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - description='Run all tests of tracing project.') - parser.add_argument('--chrome_path', type=str, - help='Path to Chrome browser binary.') - args = parser.parse_args() - chrome_command = args.chrome_path - if not chrome_command: - chrome_command = _TryGettingChromeCommand() - - run_py_tests_exit_code = _RunPyTests() - run_d8_tests_exit_code = _RunD8Tests() - if chrome_command: - run_dev_server_exit_code = _RunDevServer(chrome_command) - else: - logging.warning( - 'Could not run browser tests because chrome is missing.') - run_dev_server_exit_code = 0 - - exit_code = (run_py_tests_exit_code | run_dev_server_exit_code | - run_d8_tests_exit_code) - if exit_code: - print (bcolors.FAIL + - 'Oooops! Looks like some of your tests have failed.' + - bcolors.ENDC), u'\U0001F631'.encode('utf-8') - else: - print (bcolors.OKGREEN + - 'Woho! All the tests have passed. You are awesome!' + - bcolors.ENDC), u'\U0001F601'.encode('utf-8') - - if run_py_tests_exit_code: - sys.stderr.write( - 'run_py_tests have some failed tests. Rerun run_py_tests script ' - 'to see those.\n') - if run_d8_tests_exit_code: - sys.stderr.write( - 'run_d8_tests have some failed tests. Rerun run_py_tests script ' - 'to see those.\n') - if run_dev_server_exit_code: - sys.stderr.write( - 'run_dev_server have some failed tests. Rerun run_dev_server script ' - 'and open the browser to see those.\n') - - sys.exit(exit_code) diff --git a/src/tools/google_trace_viewer/tracing/skp_data/google_homepage.skp b/src/tools/google_trace_viewer/tracing/skp_data/google_homepage.skp deleted file mode 100755 index 52d34bf5..00000000 Binary files a/src/tools/google_trace_viewer/tracing/skp_data/google_homepage.skp and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/skp_data/lthi_cats.skp b/src/tools/google_trace_viewer/tracing/skp_data/lthi_cats.skp deleted file mode 100755 index 02a2ea50..00000000 Binary files a/src/tools/google_trace_viewer/tracing/skp_data/lthi_cats.skp and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/third_party/chai/LICENSE b/src/tools/google_trace_viewer/tracing/third_party/chai/LICENSE deleted file mode 100755 index 227b598f..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/chai/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2011-2015 Jake Luer jake@alogicalparadox.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/tools/google_trace_viewer/tracing/third_party/chai/README.chromium b/src/tools/google_trace_viewer/tracing/third_party/chai/README.chromium deleted file mode 100755 index 4a1fb8e7..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/chai/README.chromium +++ /dev/null @@ -1,15 +0,0 @@ -Name: chai -Short Name: chai -URL: https://github.com/chaijs/chai -Version: 2.1.2 -Revision: 1abc3845e3ef96afa003d62478692a1cb9a435b0 -Date: Fri Mar 20 09:46:02 2015 +0000 -License: MIT -License File: NOT_SHIPPED -Security Critical: no - -Description: -BDD / TDD assertion framework for node.js and the browser that can be paired with any testing framework. - -Local Modifications: -Copied license text out of README.md. Unminified chai.js and ripped out parts pertaining to Buffer because we're not using node and don't want could-not-require exceptions to be thrown. Reminified to prevent jslint from complaining. diff --git a/src/tools/google_trace_viewer/tracing/third_party/chai/chai.js b/src/tools/google_trace_viewer/tracing/third_party/chai/chai.js deleted file mode 100755 index 59568537..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/chai/chai.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(){function require(e){var t=require.modules[e];if(t)return"exports"in t||"function"!=typeof t.definition||(t.client=t.component=!0,t.definition.call(this,t.exports={},t),delete t.definition),t.exports}require.loader="component",require.helper={},require.helper.semVerSort=function(e,t){for(var r=e.version.split("."),i=t.version.split("."),n=0;ns?1:-1;var a=r[n].substr((""+o).length),c=i[n].substr((""+s).length);if(""===a&&""!==c)return 1;if(""!==a&&""===c)return-1;if(""!==a&&""!==c)return a>c?1:-1}return 0},require.latest=function(e,t){function r(e){throw new Error('failed to find latest module of "'+e+'"')}var i=/(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/,n=/(.*)~(.*)/;n.test(e)||r(e);for(var o=Object.keys(require.modules),s=[],a=[],c=0;c0){var f=s.sort(require.helper.semVerSort).pop().name;return t===!0?f:require(f)}var f=a.sort(function(e,t){return e.name>t.name})[0].name;return t===!0?f:require(f)},require.modules={},require.register=function(e,t){require.modules[e]={definition:t}},require.define=function(e,t){require.modules[e]={exports:t}},require.register("chaijs~assertion-error@1.0.0",function(e,t){function r(){function e(e,r){Object.keys(r).forEach(function(i){~t.indexOf(i)||(e[i]=r[i])})}var t=[].slice.call(arguments);return function(){for(var t=[].slice.call(arguments),r=0,i={};r=0;n--)if(l=o[n],!r(e[l],t[l],i))return!1;return!0}var f=require("chaijs~type-detect@0.1.1");t.exports=r}),require.register("chai",function(e,t){t.exports=require("chai/lib/chai.js")}),require.register("chai/lib/chai.js",function(e,t){var r=[],e=t.exports={};e.version="2.1.0",e.AssertionError=require("chaijs~assertion-error@1.0.0");var i=require("chai/lib/chai/utils/index.js");e.use=function(e){return~r.indexOf(e)||(e(this,i),r.push(e)),this},e.util=i;var n=require("chai/lib/chai/config.js");e.config=n;var o=require("chai/lib/chai/assertion.js");e.use(o);var s=require("chai/lib/chai/core/assertions.js");e.use(s);var a=require("chai/lib/chai/interface/expect.js");e.use(a);var c=require("chai/lib/chai/interface/should.js");e.use(c);var u=require("chai/lib/chai/interface/assert.js");e.use(u)}),require.register("chai/lib/chai/assertion.js",function(e,t){var r=require("chai/lib/chai/config.js");t.exports=function(e,t){function i(e,t,r){o(this,"ssfi",r||arguments.callee),o(this,"object",e),o(this,"message",t)}var n=e.AssertionError,o=t.flag;e.Assertion=i,Object.defineProperty(i,"includeStack",{get:function(){return console.warn("Assertion.includeStack is deprecated, use chai.config.includeStack instead."),r.includeStack},set:function(e){console.warn("Assertion.includeStack is deprecated, use chai.config.includeStack instead."),r.includeStack=e}}),Object.defineProperty(i,"showDiff",{get:function(){return console.warn("Assertion.showDiff is deprecated, use chai.config.showDiff instead."),r.showDiff},set:function(e){console.warn("Assertion.showDiff is deprecated, use chai.config.showDiff instead."),r.showDiff=e}}),i.addProperty=function(e,r){t.addProperty(this.prototype,e,r)},i.addMethod=function(e,r){t.addMethod(this.prototype,e,r)},i.addChainableMethod=function(e,r,i){t.addChainableMethod(this.prototype,e,r,i)},i.overwriteProperty=function(e,r){t.overwriteProperty(this.prototype,e,r)},i.overwriteMethod=function(e,r){t.overwriteMethod(this.prototype,e,r)},i.overwriteChainableMethod=function(e,r,i){t.overwriteChainableMethod(this.prototype,e,r,i)},i.prototype.assert=function(e,i,s,a,c,u){var h=t.test(this,arguments);if(!0!==u&&(u=!1),!0!==r.showDiff&&(u=!1),!h){var i=t.getMessage(this,arguments),l=t.getActual(this,arguments);throw new n(i,{actual:l,expected:a,showDiff:u},r.includeStack?this.assert:o(this,"ssfi"))}},Object.defineProperty(i.prototype,"_obj",{get:function(){return o(this,"object")},set:function(e){o(this,"object",e)}})}}),require.register("chai/lib/chai/config.js",function(e,t){t.exports={includeStack:!1,showDiff:!0,truncateThreshold:40}}),require.register("chai/lib/chai/core/assertions.js",function(e,t){t.exports=function(e,t){function r(e,r){r&&q(this,"message",r),e=e.toLowerCase();var i=q(this,"object"),n=~["a","e","i","o","u"].indexOf(e.charAt(0))?"an ":"a ";this.assert(e===t.type(i),"expected #{this} to be "+n+e,"expected #{this} not to be "+n+e)}function i(){q(this,"contains",!0)}function n(e,r){r&&q(this,"message",r);var i=q(this,"object"),n=!1;if("array"===t.type(i)&&"object"===t.type(e)){for(var o in i)if(t.eql(i[o],e)){n=!0;break}}else if("object"===t.type(e)){if(!q(this,"negate")){for(var s in e)new m(i).property(s,e[s]);return}var a={};for(var s in e)a[s]=i[s];n=t.eql(a,e)}else n=i&&~i.indexOf(e);this.assert(n,"expected #{this} to include "+t.inspect(e),"expected #{this} to not include "+t.inspect(e))}function o(){var e=q(this,"object"),t=Object.prototype.toString.call(e);this.assert("[object Arguments]"===t,"expected #{this} to be arguments but got "+t,"expected #{this} to not be arguments")}function s(e,t){t&&q(this,"message",t);var r=q(this,"object");return q(this,"deep")?this.eql(e):void this.assert(e===r,"expected #{this} to equal #{exp}","expected #{this} to not equal #{exp}",e,this._obj,!0)}function a(e,r){r&&q(this,"message",r),this.assert(t.eql(e,q(this,"object")),"expected #{this} to deeply equal #{exp}","expected #{this} to not deeply equal #{exp}",e,this._obj,!0)}function c(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(i>e,"expected #{this} to have a length above #{exp} but got #{act}","expected #{this} to not have a length above #{exp}",e,i)}else this.assert(r>e,"expected #{this} to be above "+e,"expected #{this} to be at most "+e)}function u(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(i>=e,"expected #{this} to have a length at least #{exp} but got #{act}","expected #{this} to have a length below #{exp}",e,i)}else this.assert(r>=e,"expected #{this} to be at least "+e,"expected #{this} to be below "+e)}function h(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(e>i,"expected #{this} to have a length below #{exp} but got #{act}","expected #{this} to not have a length below #{exp}",e,i)}else this.assert(e>r,"expected #{this} to be below "+e,"expected #{this} to be at least "+e)}function l(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(e>=i,"expected #{this} to have a length at most #{exp} but got #{act}","expected #{this} to have a length above #{exp}",e,i)}else this.assert(e>=r,"expected #{this} to be at most "+e,"expected #{this} to be above "+e)}function f(e,r){r&&q(this,"message",r);var i=t.getName(e);this.assert(q(this,"object")instanceof e,"expected #{this} to be an instance of "+i,"expected #{this} to not be an instance of "+i)}function p(e,r){r&&q(this,"message",r);var i=q(this,"object");this.assert(i.hasOwnProperty(e),"expected #{this} to have own property "+t.inspect(e),"expected #{this} to not have own property "+t.inspect(e))}function d(){q(this,"doLength",!0)}function g(e,t){t&&q(this,"message",t);var r=q(this,"object");new m(r,t).to.have.property("length");var i=r.length;this.assert(i==e,"expected #{this} to have a length of #{exp} but got #{act}","expected #{this} to not have a length of #{act}",e,i)}function b(e){var r,i=q(this,"object"),n=!0,o="keys must be given single argument of Array|Object|String, or multiple String arguments";switch(t.type(e)){case"array":if(arguments.length>1)throw new Error(o);break;case"object":if(arguments.length>1)throw new Error(o);e=Object.keys(e);break;default:e=Array.prototype.slice.call(arguments)}if(!e.length)throw new Error("keys required");var s=Object.keys(i),a=e,c=e.length,u=q(this,"any"),h=q(this,"all");if(u||h||(h=!0),u){var l=a.filter(function(e){return~s.indexOf(e)});n=l.length>0}if(h&&(n=e.every(function(e){return~s.indexOf(e)}),q(this,"negate")||q(this,"contains")||(n=n&&e.length==s.length)),c>1){e=e.map(function(e){return t.inspect(e)});var f=e.pop();h&&(r=e.join(", ")+", and "+f),u&&(r=e.join(", ")+", or "+f)}else r=t.inspect(e[0]);r=(c>1?"keys ":"key ")+r,r=(q(this,"contains")?"contain ":"have ")+r,this.assert(n,"expected #{this} to "+r,"expected #{this} to not "+r,a.slice(0).sort(),s.sort(),!0)}function v(e,r,i){i&&q(this,"message",i);var n=q(this,"object");new m(n,i).is.a("function");var o=!1,s=null,a=null,c=null;0===arguments.length?(r=null,e=null):e&&(e instanceof RegExp||"string"==typeof e)?(r=e,e=null):e&&e instanceof Error?(s=e,e=null,r=null):"function"==typeof e?(a=e.prototype.name||e.name,"Error"===a&&e!==Error&&(a=(new e).name)):e=null;try{n()}catch(u){if(s)return this.assert(u===s,"expected #{this} to throw #{exp} but #{act} was thrown","expected #{this} to not throw #{exp}",s instanceof Error?s.toString():s,u instanceof Error?u.toString():u),q(this,"object",u),this;if(e&&(this.assert(u instanceof e,"expected #{this} to throw #{exp} but #{act} was thrown","expected #{this} to not throw #{exp} but #{act} was thrown",a,u instanceof Error?u.toString():u),!r))return q(this,"object",u),this;var h="object"===t.type(u)&&"message"in u?u.message:""+u;if(null!=h&&r&&r instanceof RegExp)return this.assert(r.exec(h),"expected #{this} to throw error matching #{exp} but got #{act}","expected #{this} to throw error not matching #{exp}",r,h),q(this,"object",u),this;if(null!=h&&r&&"string"==typeof r)return this.assert(~h.indexOf(r),"expected #{this} to throw error including #{exp} but got #{act}","expected #{this} to throw error not including #{act}",r,h),q(this,"object",u),this;o=!0,c=u}var l="",f=null!==a?a:s?"#{exp}":"an error";o&&(l=" but #{act} was thrown"),this.assert(o===!0,"expected #{this} to throw "+f+l,"expected #{this} to not throw "+f+l,s instanceof Error?s.toString():s,c instanceof Error?c.toString():c),q(this,"object",c)}function y(e,t,r){return e.every(function(e){return r?t.some(function(t){return r(e,t)}):-1!==t.indexOf(e)})}function j(e,t,r){r&&q(this,"message",r);var i=q(this,"object");new m(e,r).to.have.property(t),new m(i).is.a("function");var n=e[t];i(),this.assert(n!==e[t],"expected ."+t+" to change","expected ."+t+" to not change")}function w(e,t,r){r&&q(this,"message",r);var i=q(this,"object");new m(e,r).to.have.property(t),new m(i).is.a("function");var n=e[t];i(),this.assert(e[t]-n>0,"expected ."+t+" to increase","expected ."+t+" to not increase")}function x(e,t,r){r&&q(this,"message",r);var i=q(this,"object");new m(e,r).to.have.property(t),new m(i).is.a("function");var n=e[t];i(),this.assert(e[t]-n<0,"expected ."+t+" to decrease","expected ."+t+" to not decrease")}var m=e.Assertion,q=(Object.prototype.toString,t.flag);["to","be","been","is","and","has","have","with","that","which","at","of","same"].forEach(function(e){m.addProperty(e,function(){return this})}),m.addProperty("not",function(){q(this,"negate",!0)}),m.addProperty("deep",function(){q(this,"deep",!0)}),m.addProperty("any",function(){q(this,"any",!0),q(this,"all",!1)}),m.addProperty("all",function(){q(this,"all",!0),q(this,"any",!1)}),m.addChainableMethod("an",r),m.addChainableMethod("a",r),m.addChainableMethod("include",n,i),m.addChainableMethod("contain",n,i),m.addChainableMethod("contains",n,i),m.addChainableMethod("includes",n,i),m.addProperty("ok",function(){this.assert(q(this,"object"),"expected #{this} to be truthy","expected #{this} to be falsy")}),m.addProperty("true",function(){this.assert(!0===q(this,"object"),"expected #{this} to be true","expected #{this} to be false",this.negate?!1:!0)}),m.addProperty("false",function(){this.assert(!1===q(this,"object"),"expected #{this} to be false","expected #{this} to be true",this.negate?!0:!1)}),m.addProperty("null",function(){this.assert(null===q(this,"object"),"expected #{this} to be null","expected #{this} not to be null")}),m.addProperty("undefined",function(){this.assert(void 0===q(this,"object"),"expected #{this} to be undefined","expected #{this} not to be undefined")}),m.addProperty("exist",function(){this.assert(null!=q(this,"object"),"expected #{this} to exist","expected #{this} to not exist")}),m.addProperty("empty",function(){var e=q(this,"object"),t=e;Array.isArray(e)||"string"==typeof object?t=e.length:"object"==typeof e&&(t=Object.keys(e).length),this.assert(!t,"expected #{this} to be empty","expected #{this} not to be empty")}),m.addProperty("arguments",o),m.addProperty("Arguments",o),m.addMethod("equal",s),m.addMethod("equals",s),m.addMethod("eq",s),m.addMethod("eql",a),m.addMethod("eqls",a),m.addMethod("above",c),m.addMethod("gt",c),m.addMethod("greaterThan",c),m.addMethod("least",u),m.addMethod("gte",u),m.addMethod("below",h),m.addMethod("lt",h),m.addMethod("lessThan",h),m.addMethod("most",l),m.addMethod("lte",l),m.addMethod("within",function(e,t,r){r&&q(this,"message",r);var i=q(this,"object"),n=e+".."+t;if(q(this,"doLength")){new m(i,r).to.have.property("length");var o=i.length;this.assert(o>=e&&t>=o,"expected #{this} to have a length within "+n,"expected #{this} to not have a length within "+n)}else this.assert(i>=e&&t>=i,"expected #{this} to be within "+n,"expected #{this} to not be within "+n)}),m.addMethod("instanceof",f),m.addMethod("instanceOf",f),m.addMethod("property",function(e,r,i){i&&q(this,"message",i);var n=!!q(this,"deep"),o=n?"deep property ":"property ",s=q(this,"negate"),a=q(this,"object"),c=n?t.getPathInfo(e,a):null,u=n?c.exists:t.hasProperty(e,a),h=n?c.value:a[e];if(s&&void 0!==r){if(void 0===h)throw i=null!=i?i+": ":"",new Error(i+t.inspect(a)+" has no "+o+t.inspect(e))}else this.assert(u,"expected #{this} to have a "+o+t.inspect(e),"expected #{this} to not have "+o+t.inspect(e));void 0!==r&&this.assert(r===h,"expected #{this} to have a "+o+t.inspect(e)+" of #{exp}, but got #{act}","expected #{this} to not have a "+o+t.inspect(e)+" of #{act}",r,h),q(this,"object",h)}),m.addMethod("ownProperty",p),m.addMethod("haveOwnProperty",p),m.addChainableMethod("length",g,d),m.addMethod("lengthOf",g),m.addMethod("match",function(e,t){t&&q(this,"message",t);var r=q(this,"object");this.assert(e.exec(r),"expected #{this} to match "+e,"expected #{this} not to match "+e)}),m.addMethod("string",function(e,r){r&&q(this,"message",r);var i=q(this,"object");new m(i,r).is.a("string"),this.assert(~i.indexOf(e),"expected #{this} to contain "+t.inspect(e),"expected #{this} to not contain "+t.inspect(e))}),m.addMethod("keys",b),m.addMethod("key",b),m.addMethod("throw",v),m.addMethod("throws",v),m.addMethod("Throw",v),m.addMethod("respondTo",function(e,r){r&&q(this,"message",r);var i=q(this,"object"),n=q(this,"itself"),o="function"!==t.type(i)||n?i[e]:i.prototype[e];this.assert("function"==typeof o,"expected #{this} to respond to "+t.inspect(e),"expected #{this} to not respond to "+t.inspect(e))}),m.addProperty("itself",function(){q(this,"itself",!0)}),m.addMethod("satisfy",function(e,r){r&&q(this,"message",r);var i=q(this,"object"),n=e(i);this.assert(n,"expected #{this} to satisfy "+t.objDisplay(e),"expected #{this} to not satisfy"+t.objDisplay(e),this.negate?!1:!0,n)}),m.addMethod("closeTo",function(e,r,i){i&&q(this,"message",i);var n=q(this,"object");if(new m(n,i).is.a("number"),"number"!==t.type(e)||"number"!==t.type(r))throw new Error("the arguments to closeTo must be numbers");this.assert(Math.abs(n-e)<=r,"expected #{this} to be close to "+e+" +/- "+r,"expected #{this} not to be close to "+e+" +/- "+r)}),m.addMethod("members",function(e,r){r&&q(this,"message",r);var i=q(this,"object");new m(i).to.be.an("array"),new m(e).to.be.an("array");var n=q(this,"deep")?t.eql:void 0;return q(this,"contains")?this.assert(y(e,i,n),"expected #{this} to be a superset of #{act}","expected #{this} to not be a superset of #{act}",i,e):void this.assert(y(i,e,n)&&y(e,i,n),"expected #{this} to have the same members as #{act}","expected #{this} to not have the same members as #{act}",i,e)}),m.addChainableMethod("change",j),m.addChainableMethod("changes",j),m.addChainableMethod("increase",w),m.addChainableMethod("increases",w),m.addChainableMethod("decrease",x),m.addChainableMethod("decreases",x)}}),require.register("chai/lib/chai/interface/assert.js",function(exports,module){module.exports=function(chai,util){var Assertion=chai.Assertion,flag=util.flag,assert=chai.assert=function(e,t){var r=new Assertion(null,null,chai.assert);r.assert(e,t,"[ negation message unavailable ]")};assert.fail=function(e,t,r,i){throw r=r||"assert.fail()",new chai.AssertionError(r,{actual:e,expected:t,operator:i},assert.fail)},assert.ok=function(e,t){new Assertion(e,t).is.ok},assert.notOk=function(e,t){new Assertion(e,t).is.not.ok},assert.equal=function(e,t,r){var i=new Assertion(e,r,assert.equal);i.assert(t==flag(i,"object"),"expected #{this} to equal #{exp}","expected #{this} to not equal #{act}",t,e)},assert.notEqual=function(e,t,r){var i=new Assertion(e,r,assert.notEqual);i.assert(t!=flag(i,"object"),"expected #{this} to not equal #{exp}","expected #{this} to equal #{act}",t,e)},assert.strictEqual=function(e,t,r){new Assertion(e,r).to.equal(t)},assert.notStrictEqual=function(e,t,r){new Assertion(e,r).to.not.equal(t)},assert.deepEqual=function(e,t,r){new Assertion(e,r).to.eql(t)},assert.notDeepEqual=function(e,t,r){new Assertion(e,r).to.not.eql(t)},assert.isAbove=function(e,t,r){new Assertion(e,r).to.be.above(t)},assert.isBelow=function(e,t,r){new Assertion(e,r).to.be.below(t)},assert.isTrue=function(e,t){new Assertion(e,t).is["true"]},assert.isFalse=function(e,t){new Assertion(e,t).is["false"]},assert.isNull=function(e,t){new Assertion(e,t).to.equal(null)},assert.isNotNull=function(e,t){new Assertion(e,t).to.not.equal(null)},assert.isUndefined=function(e,t){new Assertion(e,t).to.equal(void 0)},assert.isDefined=function(e,t){new Assertion(e,t).to.not.equal(void 0)},assert.isFunction=function(e,t){new Assertion(e,t).to.be.a("function")},assert.isNotFunction=function(e,t){new Assertion(e,t).to.not.be.a("function")},assert.isObject=function(e,t){new Assertion(e,t).to.be.a("object")},assert.isNotObject=function(e,t){new Assertion(e,t).to.not.be.a("object")},assert.isArray=function(e,t){new Assertion(e,t).to.be.an("array")},assert.isNotArray=function(e,t){new Assertion(e,t).to.not.be.an("array")},assert.isString=function(e,t){new Assertion(e,t).to.be.a("string")},assert.isNotString=function(e,t){new Assertion(e,t).to.not.be.a("string")},assert.isNumber=function(e,t){new Assertion(e,t).to.be.a("number")},assert.isNotNumber=function(e,t){new Assertion(e,t).to.not.be.a("number")},assert.isBoolean=function(e,t){new Assertion(e,t).to.be.a("boolean")},assert.isNotBoolean=function(e,t){new Assertion(e,t).to.not.be.a("boolean")},assert.typeOf=function(e,t,r){new Assertion(e,r).to.be.a(t)},assert.notTypeOf=function(e,t,r){new Assertion(e,r).to.not.be.a(t)},assert.instanceOf=function(e,t,r){new Assertion(e,r).to.be.instanceOf(t)},assert.notInstanceOf=function(e,t,r){new Assertion(e,r).to.not.be.instanceOf(t)},assert.include=function(e,t,r){new Assertion(e,r,assert.include).include(t)},assert.notInclude=function(e,t,r){new Assertion(e,r,assert.notInclude).not.include(t)},assert.match=function(e,t,r){new Assertion(e,r).to.match(t)},assert.notMatch=function(e,t,r){new Assertion(e,r).to.not.match(t)},assert.property=function(e,t,r){new Assertion(e,r).to.have.property(t)},assert.notProperty=function(e,t,r){new Assertion(e,r).to.not.have.property(t)},assert.deepProperty=function(e,t,r){new Assertion(e,r).to.have.deep.property(t)},assert.notDeepProperty=function(e,t,r){new Assertion(e,r).to.not.have.deep.property(t)},assert.propertyVal=function(e,t,r,i){new Assertion(e,i).to.have.property(t,r)},assert.propertyNotVal=function(e,t,r,i){new Assertion(e,i).to.not.have.property(t,r)},assert.deepPropertyVal=function(e,t,r,i){new Assertion(e,i).to.have.deep.property(t,r)},assert.deepPropertyNotVal=function(e,t,r,i){new Assertion(e,i).to.not.have.deep.property(t,r)},assert.lengthOf=function(e,t,r){new Assertion(e,r).to.have.length(t)},assert.Throw=function(e,t,r,i){("string"==typeof t||t instanceof RegExp)&&(r=t,t=null);var n=new Assertion(e,i).to.Throw(t,r);return flag(n,"object")},assert.doesNotThrow=function(e,t,r){"string"==typeof t&&(r=t,t=null),new Assertion(e,r).to.not.Throw(t)},assert.operator=function(val,operator,val2,msg){if(!~["==","===",">",">=","<","<=","!=","!=="].indexOf(operator))throw new Error('Invalid operator "'+operator+'"');var test=new Assertion(eval(val+operator+val2),msg);test.assert(!0===flag(test,"object"),"expected "+util.inspect(val)+" to be "+operator+" "+util.inspect(val2),"expected "+util.inspect(val)+" to not be "+operator+" "+util.inspect(val2))},assert.closeTo=function(e,t,r,i){new Assertion(e,i).to.be.closeTo(t,r)},assert.sameMembers=function(e,t,r){new Assertion(e,r).to.have.same.members(t)},assert.sameDeepMembers=function(e,t,r){new Assertion(e,r).to.have.same.deep.members(t)},assert.includeMembers=function(e,t,r){new Assertion(e,r).to.include.members(t)},assert.changes=function(e,t,r){new Assertion(e).to.change(t,r)},assert.doesNotChange=function(e,t,r){new Assertion(e).to.not.change(t,r)},assert.increases=function(e,t,r){new Assertion(e).to.increase(t,r)},assert.doesNotIncrease=function(e,t,r){new Assertion(e).to.not.increase(t,r)},assert.decreases=function(e,t,r){new Assertion(e).to.decrease(t,r)},assert.doesNotDecrease=function(e,t,r){new Assertion(e).to.not.decrease(t,r)},assert.ifError=function(e,t){new Assertion(e,t).to.not.be.ok},function e(t,r){return assert[r]=assert[t],e}("Throw","throw")("Throw","throws")}}),require.register("chai/lib/chai/interface/expect.js",function(e,t){t.exports=function(e){e.expect=function(t,r){return new e.Assertion(t,r)},e.expect.fail=function(t,r,i,n){throw i=i||"expect.fail()",new e.AssertionError(i,{actual:t,expected:r,operator:n},e.expect.fail)}}}),require.register("chai/lib/chai/interface/should.js",function(e,t){t.exports=function(e){function t(){function t(){return this instanceof String||this instanceof Number?new r(this.constructor(this),null,t):this instanceof Boolean?new r(1==this,null,t):new r(this,null,t)}function i(e){Object.defineProperty(this,"should",{value:e,enumerable:!0,configurable:!0,writable:!0})}Object.defineProperty(Object.prototype,"should",{set:i,get:t,configurable:!0});var n={};return n.fail=function(t,r,i,o){throw i=i||"should.fail()",new e.AssertionError(i,{actual:t,expected:r,operator:o},n.fail)},n.equal=function(e,t,i){new r(e,i).to.equal(t)},n.Throw=function(e,t,i,n){new r(e,n).to.Throw(t,i)},n.exist=function(e,t){new r(e,t).to.exist},n.not={},n.not.equal=function(e,t,i){new r(e,i).to.not.equal(t)},n.not.Throw=function(e,t,i,n){new r(e,n).to.not.Throw(t,i)},n.not.exist=function(e,t){new r(e,t).to.not.exist},n["throw"]=n.Throw,n.not["throw"]=n.not.Throw,n}var r=e.Assertion;e.should=t,e.Should=t}}),require.register("chai/lib/chai/utils/addChainableMethod.js",function(e,t){var r=require("chai/lib/chai/utils/transferFlags.js"),i=require("chai/lib/chai/utils/flag.js"),n=require("chai/lib/chai/config.js"),o="__proto__"in Object,s=/^(?:length|name|arguments|caller)$/,a=Function.prototype.call,c=Function.prototype.apply;t.exports=function(e,t,u,h){"function"!=typeof h&&(h=function(){});var l={method:u,chainingBehavior:h};e.__methods||(e.__methods={}),e.__methods[t]=l,Object.defineProperty(e,t,{get:function(){l.chainingBehavior.call(this);var t=function f(){var e=i(this,"ssfi");e&&n.includeStack===!1&&i(this,"ssfi",f);var t=l.method.apply(this,arguments);return void 0===t?this:t};if(o){var u=t.__proto__=Object.create(this);u.call=a,u.apply=c}else{var h=Object.getOwnPropertyNames(e);h.forEach(function(r){if(!s.test(r)){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i)}})}return r(this,t),t},configurable:!0})}}),require.register("chai/lib/chai/utils/addMethod.js",function(e,t){var r=require("chai/lib/chai/config.js"),i=require("chai/lib/chai/utils/flag.js");t.exports=function(e,t,n){e[t]=function(){var o=i(this,"ssfi");o&&r.includeStack===!1&&i(this,"ssfi",e[t]);var s=n.apply(this,arguments);return void 0===s?this:s}}}),require.register("chai/lib/chai/utils/addProperty.js",function(e,t){t.exports=function(e,t,r){Object.defineProperty(e,t,{get:function(){var e=r.call(this);return void 0===e?this:e},configurable:!0})}}),require.register("chai/lib/chai/utils/flag.js",function(e,t){t.exports=function(e,t,r){var i=e.__flags||(e.__flags=Object.create(null));return 3!==arguments.length?i[t]:void(i[t]=r)}}),require.register("chai/lib/chai/utils/getActual.js",function(e,t){t.exports=function(e,t){return t.length>4?t[4]:e._obj}}),require.register("chai/lib/chai/utils/getEnumerableProperties.js",function(e,t){t.exports=function(e){var t=[];for(var r in e)t.push(r);return t}}),require.register("chai/lib/chai/utils/getMessage.js",function(e,t){var r=require("chai/lib/chai/utils/flag.js"),i=require("chai/lib/chai/utils/getActual.js"),n=(require("chai/lib/chai/utils/inspect.js"),require("chai/lib/chai/utils/objDisplay.js"));t.exports=function(e,t){var o=r(e,"negate"),s=r(e,"object"),a=t[3],c=i(e,t),u=o?t[2]:t[1],h=r(e,"message");return"function"==typeof u&&(u=u()),u=u||"",u=u.replace(/#{this}/g,n(s)).replace(/#{act}/g,n(c)).replace(/#{exp}/g,n(a)),h?h+": "+u:u}}),require.register("chai/lib/chai/utils/getName.js",function(e,t){t.exports=function(e){if(e.name)return e.name;var t=/^\s?function ([^(]*)\(/.exec(e);return t&&t[1]?t[1]:""}}),require.register("chai/lib/chai/utils/getPathValue.js",function(e,t){var r=require("chai/lib/chai/utils/getPathInfo.js");t.exports=function(e,t){var i=r(e,t);return i.value}}),require.register("chai/lib/chai/utils/getPathInfo.js",function(e,t){function r(e){var t=e.replace(/\[/g,".["),r=t.match(/(\\\.|[^.]+?)+/g);return r.map(function(e){var t=/\[(\d+)\]$/,r=t.exec(e);return r?{i:parseFloat(r[1])}:{p:e}})}function i(e,t,r){var i,n=t;r=void 0===r?e.length:r;for(var o=0,s=r;s>o;o++){var a=e[o];n?("undefined"!=typeof a.p?n=n[a.p]:"undefined"!=typeof a.i&&(n=n[a.i]),o==s-1&&(i=n)):i=void 0}return i}var n=require("chai/lib/chai/utils/hasProperty.js");t.exports=function(e,t){var o=r(e),s=o[o.length-1],a={parent:i(o,t,o.length-1),name:s.p||s.i,value:i(o,t)};return a.exists=n(a.name,a.parent),a}}),require.register("chai/lib/chai/utils/hasProperty.js",function(e,t){var r=require("chai/lib/chai/utils/type.js"),i={number:Number,string:String};t.exports=function(e,t){var n=r(t);return"null"===n||"undefined"===n?!1:(i[n]&&"object"!=typeof t&&(t=new i[n](t)),e in t)}}),require.register("chai/lib/chai/utils/getProperties.js",function(e,t){t.exports=function(){function e(e){-1===t.indexOf(e)&&t.push(e)}for(var t=Object.getOwnPropertyNames(subject),r=Object.getPrototypeOf(subject);null!==r;)Object.getOwnPropertyNames(r).forEach(e),r=Object.getPrototypeOf(r);return t}}),require.register("chai/lib/chai/utils/index.js",function(e,t){var e=t.exports={};e.test=require("chai/lib/chai/utils/test.js"),e.type=require("chai/lib/chai/utils/type.js"),e.getMessage=require("chai/lib/chai/utils/getMessage.js"),e.getActual=require("chai/lib/chai/utils/getActual.js"),e.inspect=require("chai/lib/chai/utils/inspect.js"),e.objDisplay=require("chai/lib/chai/utils/objDisplay.js"),e.flag=require("chai/lib/chai/utils/flag.js"),e.transferFlags=require("chai/lib/chai/utils/transferFlags.js"),e.eql=require("chaijs~deep-eql@0.1.3"),e.getPathValue=require("chai/lib/chai/utils/getPathValue.js"),e.getPathInfo=require("chai/lib/chai/utils/getPathInfo.js"),e.hasProperty=require("chai/lib/chai/utils/hasProperty.js"),e.getName=require("chai/lib/chai/utils/getName.js"),e.addProperty=require("chai/lib/chai/utils/addProperty.js"),e.addMethod=require("chai/lib/chai/utils/addMethod.js"),e.overwriteProperty=require("chai/lib/chai/utils/overwriteProperty.js"),e.overwriteMethod=require("chai/lib/chai/utils/overwriteMethod.js"),e.addChainableMethod=require("chai/lib/chai/utils/addChainableMethod.js"),e.overwriteChainableMethod=require("chai/lib/chai/utils/overwriteChainableMethod.js")}),require.register("chai/lib/chai/utils/inspect.js",function(e,t){function r(e,t,r){var n={showHidden:t,seen:[],stylize:function(e){return e}};return i(n,e,"undefined"==typeof r?2:r)}function i(t,r,p){if(r&&"function"==typeof r.inspect&&r.inspect!==e.inspect&&(!r.constructor||r.constructor.prototype!==r)){var y=r.inspect(p);return"string"!=typeof y&&(y=i(t,y,p)),y}var j=n(t,r);if(j)return j;if(v(r)){if("outerHTML"in r)return r.outerHTML;try{if(document.xmlVersion){var w=new XMLSerializer;return w.serializeToString(r)}var x="http://www.w3.org/1999/xhtml",m=document.createElementNS(x,"_");return m.appendChild(r.cloneNode(!1)),html=m.innerHTML.replace("><",">"+r.innerHTML+"<"),m.innerHTML="",html}catch(q){}}var A=b(r),O=t.showHidden?g(r):A;if(0===O.length||f(r)&&(1===O.length&&"stack"===O[0]||2===O.length&&"description"===O[0]&&"stack"===O[1])){if("function"==typeof r){var M=d(r),P=M?": "+M:"";return t.stylize("[Function"+P+"]","special")}if(h(r))return t.stylize(RegExp.prototype.toString.call(r),"regexp");if(l(r))return t.stylize(Date.prototype.toUTCString.call(r),"date");if(f(r))return o(r)}var S="",E=!1,_=["{","}"];if(u(r)&&(E=!0,_=["[","]"]),"function"==typeof r){var M=d(r),P=M?": "+M:"";S=" [Function"+P+"]"}if(h(r)&&(S=" "+RegExp.prototype.toString.call(r)),l(r)&&(S=" "+Date.prototype.toUTCString.call(r)), -f(r))return o(r);if(0===O.length&&(!E||0==r.length))return _[0]+S+_[1];if(0>p)return h(r)?t.stylize(RegExp.prototype.toString.call(r),"regexp"):t.stylize("[Object]","special");t.seen.push(r);var k;return k=E?s(t,r,p,A,O):O.map(function(e){return a(t,r,p,A,e,E)}),t.seen.pop(),c(k,S,_)}function n(e,t){switch(typeof t){case"undefined":return e.stylize("undefined","undefined");case"string":var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string");case"number":return 0===t&&1/t===-(1/0)?e.stylize("-0","number"):e.stylize(""+t,"number");case"boolean":return e.stylize(""+t,"boolean")}return null===t?e.stylize("null","null"):void 0}function o(e){return"["+Error.prototype.toString.call(e)+"]"}function s(e,t,r,i,n){for(var o=[],s=0,c=t.length;c>s;++s)o.push(Object.prototype.hasOwnProperty.call(t,String(s))?a(e,t,r,i,String(s),!0):"");return n.forEach(function(n){n.match(/^\d+$/)||o.push(a(e,t,r,i,n,!0))}),o}function a(e,t,r,n,o,s){var a,c;if(t.__lookupGetter__&&(t.__lookupGetter__(o)?c=t.__lookupSetter__(o)?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):t.__lookupSetter__(o)&&(c=e.stylize("[Setter]","special"))),n.indexOf(o)<0&&(a="["+o+"]"),c||(e.seen.indexOf(t[o])<0?(c=null===r?i(e,t[o],null):i(e,t[o],r-1),c.indexOf("\n")>-1&&(c=s?c.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+c.split("\n").map(function(e){return" "+e}).join("\n"))):c=e.stylize("[Circular]","special")),"undefined"==typeof a){if(s&&o.match(/^\d+$/))return c;a=JSON.stringify(""+o),a.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+c}function c(e,t,r){var i=0,n=e.reduce(function(e,t){return i++,t.indexOf("\n")>=0&&i++,e+t.length+1},0);return n>60?r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1]:r[0]+t+" "+e.join(", ")+" "+r[1]}function u(e){return Array.isArray(e)||"object"==typeof e&&"[object Array]"===p(e)}function h(e){return"object"==typeof e&&"[object RegExp]"===p(e)}function l(e){return"object"==typeof e&&"[object Date]"===p(e)}function f(e){return"object"==typeof e&&"[object Error]"===p(e)}function p(e){return Object.prototype.toString.call(e)}var d=require("chai/lib/chai/utils/getName.js"),g=require("chai/lib/chai/utils/getProperties.js"),b=require("chai/lib/chai/utils/getEnumerableProperties.js");t.exports=r;var v=function(e){return"object"==typeof HTMLElement?e instanceof HTMLElement:e&&"object"==typeof e&&1===e.nodeType&&"string"==typeof e.nodeName}}),require.register("chai/lib/chai/utils/objDisplay.js",function(e,t){var r=require("chai/lib/chai/utils/inspect.js"),i=require("chai/lib/chai/config.js");t.exports=function(e){var t=r(e),n=Object.prototype.toString.call(e);if(i.truncateThreshold&&t.length>=i.truncateThreshold){if("[object Function]"===n)return e.name&&""!==e.name?"[Function: "+e.name+"]":"[Function]";if("[object Array]"===n)return"[ Array("+e.length+") ]";if("[object Object]"===n){var o=Object.keys(e),s=o.length>2?o.splice(0,2).join(", ")+", ...":o.join(", ");return"{ Object ("+s+") }"}return t}return t}}),require.register("chai/lib/chai/utils/overwriteMethod.js",function(e,t){t.exports=function(e,t,r){var i=e[t],n=function(){return this};i&&"function"==typeof i&&(n=i),e[t]=function(){var e=r(n).apply(this,arguments);return void 0===e?this:e}}}),require.register("chai/lib/chai/utils/overwriteProperty.js",function(e,t){t.exports=function(e,t,r){var i=Object.getOwnPropertyDescriptor(e,t),n=function(){};i&&"function"==typeof i.get&&(n=i.get),Object.defineProperty(e,t,{get:function(){var e=r(n).call(this);return void 0===e?this:e},configurable:!0})}}),require.register("chai/lib/chai/utils/overwriteChainableMethod.js",function(e,t){t.exports=function(e,t,r,i){var n=e.__methods[t],o=n.chainingBehavior;n.chainingBehavior=function(){var e=i(o).call(this);return void 0===e?this:e};var s=n.method;n.method=function(){var e=r(s).apply(this,arguments);return void 0===e?this:e}}}),require.register("chai/lib/chai/utils/test.js",function(e,t){var r=require("chai/lib/chai/utils/flag.js");t.exports=function(e,t){var i=r(e,"negate"),n=t[0];return i?!n:n}}),require.register("chai/lib/chai/utils/transferFlags.js",function(e,t){t.exports=function(e,t,r){var i=e.__flags||(e.__flags=Object.create(null));t.__flags||(t.__flags=Object.create(null)),r=3===arguments.length?r:!0;for(var n in i)(r||"object"!==n&&"ssfi"!==n&&"message"!=n)&&(t.__flags[n]=i[n])}}),require.register("chai/lib/chai/utils/type.js",function(e,t){var r={"[object Arguments]":"arguments","[object Array]":"array","[object Date]":"date","[object Function]":"function","[object Number]":"number","[object RegExp]":"regexp","[object String]":"string"};t.exports=function(e){var t=Object.prototype.toString.call(e);return r[t]?r[t]:null===e?"null":void 0===e?"undefined":e===Object(e)?"object":typeof e}}),"object"==typeof exports?module.exports=require("chai"):"function"==typeof define&&define.amd?define("chai",[],function(){return require("chai")}):(this||window).chai=require("chai")}(); diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/AUTHORS b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/AUTHORS deleted file mode 100755 index 2f72bd6b..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/AUTHORS +++ /dev/null @@ -1,6 +0,0 @@ -# This is a list of contributors to the Closure Linter. - -# Names should be added to this file like so: -# Name or Organization - -Google Inc. diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/LICENSE b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/LICENSE deleted file mode 100755 index d9a10c0d..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/README b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/README deleted file mode 100755 index 4a21b2de..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/README +++ /dev/null @@ -1,9 +0,0 @@ -This repository contains the Closure Linter - a style checker for JavaScript. - -To install the application, run - python ./setup.py install - -After installing, you get two helper applications installed into /usr/local/bin: - - gjslint.py - runs the linter and checks for errors - fixjsstyle.py - tries to fix errors automatically diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/README.chromium b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/README.chromium deleted file mode 100755 index bd972bb4..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/README.chromium +++ /dev/null @@ -1,17 +0,0 @@ -Name: closure-linter -URL: http://code.google.com/p/closure-linter/ -Version: 2.3.4 -Date: 28 Feb 2012 -Revision: 16 -License: Apache 2.0 -Security Critical: no - -Description: - The Closure Linter enforces the guidelines set by the Google JavaScript Style - Guide. The linter handles style issues so that you can focus on the code. - -Local modifications: - Removed closure_linter/testdata/ - Added Apache License notice to closure_linter/common/tokens_test.py - - Lines ending with @supress longLineCheck do not warn. \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/__init__.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/__init__.py deleted file mode 100755 index 1798c8cf..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Package indicator for gjslint.""" diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/checker.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/checker.py deleted file mode 100755 index 5c0fa818..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/checker.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Core methods for checking JS files for common style guide violations.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import gflags as flags - -from closure_linter import checkerbase -from closure_linter import closurizednamespacesinfo -from closure_linter import ecmametadatapass -from closure_linter import javascriptlintrules -from closure_linter import javascriptstatetracker -from closure_linter.common import lintrunner - -flags.DEFINE_list('limited_doc_files', ['dummy.js', 'externs.js'], - 'List of files with relaxed documentation checks. Will not ' - 'report errors for missing documentation, some missing ' - 'descriptions, or methods whose @return tags don\'t have a ' - 'matching return statement.') -flags.DEFINE_list('closurized_namespaces', '', - 'Namespace prefixes, used for testing of' - 'goog.provide/require') -flags.DEFINE_list('ignored_extra_namespaces', '', - 'Fully qualified namespaces that should be not be reported ' - 'as extra by the linter.') - - -class JavaScriptStyleChecker(checkerbase.CheckerBase): - """Checker that applies JavaScriptLintRules.""" - - def __init__(self, error_handler): - """Initialize an JavaScriptStyleChecker object. - - Args: - error_handler: Error handler to pass all errors to. - """ - self._namespaces_info = None - if flags.FLAGS.closurized_namespaces: - self._namespaces_info = ( - closurizednamespacesinfo.ClosurizedNamespacesInfo( - flags.FLAGS.closurized_namespaces, - flags.FLAGS.ignored_extra_namespaces)) - - checkerbase.CheckerBase.__init__( - self, - error_handler=error_handler, - lint_rules=javascriptlintrules.JavaScriptLintRules( - self._namespaces_info), - state_tracker=javascriptstatetracker.JavaScriptStateTracker(), - metadata_pass=ecmametadatapass.EcmaMetaDataPass(), - limited_doc_files=flags.FLAGS.limited_doc_files) - - def _CheckTokens(self, token, parse_error, debug_tokens): - """Checks a token stream for lint warnings/errors. - - Adds a separate pass for computing dependency information based on - goog.require and goog.provide statements prior to the main linting pass. - - Args: - token: The first token in the token stream. - parse_error: A ParseError if any errors occurred. - debug_tokens: Whether every token should be printed as it is encountered - during the pass. - - Returns: - A boolean indicating whether the full token stream could be checked or if - checking failed prematurely. - """ - # To maximize the amount of errors that get reported before a parse error - # is displayed, don't run the dependency pass if a parse error exists. - if self._namespaces_info and not parse_error: - self._namespaces_info.Reset() - result = (self._ExecutePass(token, self._DependencyPass) and - self._ExecutePass(token, self._LintPass, - debug_tokens=debug_tokens)) - else: - result = self._ExecutePass(token, self._LintPass, parse_error, - debug_tokens) - - if not result: - return False - - self._lint_rules.Finalize(self._state_tracker, self._tokenizer.mode) - - self._error_handler.FinishFile() - return True - - def _DependencyPass(self, token): - """Processes an invidual token for dependency information. - - Used to encapsulate the logic needed to process an individual token so that - it can be passed to _ExecutePass. - - Args: - token: The token to process. - """ - self._namespaces_info.ProcessToken(token, self._state_tracker) - - -class GJsLintRunner(lintrunner.LintRunner): - """Wrapper class to run GJsLint.""" - - def Run(self, filenames, error_handler): - """Run GJsLint on the given filenames. - - Args: - filenames: The filenames to check - error_handler: An ErrorHandler object. - """ - checker = JavaScriptStyleChecker(error_handler) - - # Check the list of files. - for filename in filenames: - checker.Check(filename) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/checkerbase.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/checkerbase.py deleted file mode 100755 index c7735a0e..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/checkerbase.py +++ /dev/null @@ -1,312 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Base classes for writing checkers that operate on tokens.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)', - 'jacobr@google.com (Jacob Richman)') - -import StringIO -import traceback - -import gflags as flags -from closure_linter import ecmametadatapass -from closure_linter import errorrules -from closure_linter import errors -from closure_linter import javascripttokenizer -from closure_linter.common import error -from closure_linter.common import htmlutil - -FLAGS = flags.FLAGS -flags.DEFINE_boolean('debug_tokens', False, - 'Whether to print all tokens for debugging.') - -flags.DEFINE_boolean('error_trace', False, - 'Whether to show error exceptions.') - - -class LintRulesBase(object): - """Base class for all classes defining the lint rules for a language.""" - - def __init__(self): - self.__checker = None - - def Initialize(self, checker, limited_doc_checks, is_html): - """Initializes to prepare to check a file. - - Args: - checker: Class to report errors to. - limited_doc_checks: Whether doc checking is relaxed for this file. - is_html: Whether the file is an HTML file with extracted contents. - """ - self.__checker = checker - self._limited_doc_checks = limited_doc_checks - self._is_html = is_html - - def _HandleError(self, code, message, token, position=None, - fix_data=None): - """Call the HandleError function for the checker we are associated with.""" - if errorrules.ShouldReportError(code): - self.__checker.HandleError(code, message, token, position, fix_data) - - def _SetLimitedDocChecks(self, limited_doc_checks): - """Sets whether doc checking is relaxed for this file. - - Args: - limited_doc_checks: Whether doc checking is relaxed for this file. - """ - self._limited_doc_checks = limited_doc_checks - - def CheckToken(self, token, parser_state): - """Checks a token, given the current parser_state, for warnings and errors. - - Args: - token: The current token under consideration. - parser_state: Object that indicates the parser state in the page. - - Raises: - TypeError: If not overridden. - """ - raise TypeError('Abstract method CheckToken not implemented') - - def Finalize(self, parser_state, tokenizer_mode): - """Perform all checks that need to occur after all lines are processed. - - Args: - parser_state: State of the parser after parsing all tokens - tokenizer_mode: Mode of the tokenizer after parsing the entire page - - Raises: - TypeError: If not overridden. - """ - raise TypeError('Abstract method Finalize not implemented') - - -class CheckerBase(object): - """This class handles checking a LintRules object against a file.""" - - def __init__(self, error_handler, lint_rules, state_tracker, - limited_doc_files=None, metadata_pass=None): - """Initialize a checker object. - - Args: - error_handler: Object that handles errors. - lint_rules: LintRules object defining lint errors given a token - and state_tracker object. - state_tracker: Object that tracks the current state in the token stream. - limited_doc_files: List of filenames that are not required to have - documentation comments. - metadata_pass: Object that builds metadata about the token stream. - """ - self._error_handler = error_handler - self._lint_rules = lint_rules - self._state_tracker = state_tracker - self._metadata_pass = metadata_pass - self._limited_doc_files = limited_doc_files - - # TODO(user): Factor out. A checker does not need to know about the - # tokenizer, only the token stream. - self._tokenizer = javascripttokenizer.JavaScriptTokenizer() - - self._has_errors = False - - def HandleError(self, code, message, token, position=None, - fix_data=None): - """Prints out the given error message including a line number. - - Args: - code: The error code. - message: The error to print. - token: The token where the error occurred, or None if it was a file-wide - issue. - position: The position of the error, defaults to None. - fix_data: Metadata used for fixing the error. - """ - self._has_errors = True - self._error_handler.HandleError( - error.Error(code, message, token, position, fix_data)) - - def HasErrors(self): - """Returns true if the style checker has found any errors. - - Returns: - True if the style checker has found any errors. - """ - return self._has_errors - - def Check(self, filename, source=None): - """Checks the file, printing warnings and errors as they are found. - - Args: - filename: The name of the file to check. - source: Optional. The contents of the file. Can be either a string or - file-like object. If omitted, contents will be read from disk from - the given filename. - """ - - if source is None: - try: - f = open(filename) - except IOError: - self._error_handler.HandleFile(filename, None) - self.HandleError(errors.FILE_NOT_FOUND, 'File not found', None) - self._error_handler.FinishFile() - return - else: - if type(source) in [str, unicode]: - f = StringIO.StringIO(source) - else: - f = source - - try: - if filename.endswith('.html') or filename.endswith('.htm'): - self.CheckLines(filename, htmlutil.GetScriptLines(f), True) - else: - self.CheckLines(filename, f, False) - finally: - f.close() - - def CheckLines(self, filename, lines_iter, is_html): - """Checks a file, given as an iterable of lines, for warnings and errors. - - Args: - filename: The name of the file to check. - lines_iter: An iterator that yields one line of the file at a time. - is_html: Whether the file being checked is an HTML file with extracted - contents. - - Returns: - A boolean indicating whether the full file could be checked or if checking - failed prematurely. - """ - limited_doc_checks = False - if self._limited_doc_files: - for limited_doc_filename in self._limited_doc_files: - if filename.endswith(limited_doc_filename): - limited_doc_checks = True - break - - lint_rules = self._lint_rules - lint_rules.Initialize(self, limited_doc_checks, is_html) - - token = self._tokenizer.TokenizeFile(lines_iter) - - parse_error = None - if self._metadata_pass: - try: - self._metadata_pass.Reset() - self._metadata_pass.Process(token) - except ecmametadatapass.ParseError, caught_parse_error: - if FLAGS.error_trace: - traceback.print_exc() - parse_error = caught_parse_error - except Exception: - print 'Internal error in %s' % filename - traceback.print_exc() - return False - - self._error_handler.HandleFile(filename, token) - - return self._CheckTokens(token, parse_error=parse_error, - debug_tokens=FLAGS.debug_tokens) - - def _CheckTokens(self, token, parse_error, debug_tokens): - """Checks a token stream for lint warnings/errors. - - Args: - token: The first token in the token stream to check. - parse_error: A ParseError if any errors occurred. - debug_tokens: Whether every token should be printed as it is encountered - during the pass. - - Returns: - A boolean indicating whether the full token stream could be checked or if - checking failed prematurely. - """ - result = self._ExecutePass(token, self._LintPass, parse_error, debug_tokens) - - if not result: - return False - - self._lint_rules.Finalize(self._state_tracker, self._tokenizer.mode) - self._error_handler.FinishFile() - return True - - def _LintPass(self, token): - """Checks an individual token for lint warnings/errors. - - Used to encapsulate the logic needed to check an individual token so that it - can be passed to _ExecutePass. - - Args: - token: The token to check. - """ - self._lint_rules.CheckToken(token, self._state_tracker) - - def _ExecutePass(self, token, pass_function, parse_error=None, - debug_tokens=False): - """Calls the given function for every token in the given token stream. - - As each token is passed to the given function, state is kept up to date and, - depending on the error_trace flag, errors are either caught and reported, or - allowed to bubble up so developers can see the full stack trace. If a parse - error is specified, the pass will proceed as normal until the token causing - the parse error is reached. - - Args: - token: The first token in the token stream. - pass_function: The function to call for each token in the token stream. - parse_error: A ParseError if any errors occurred. - debug_tokens: Whether every token should be printed as it is encountered - during the pass. - - Returns: - A boolean indicating whether the full token stream could be checked or if - checking failed prematurely. - - Raises: - Exception: If any error occurred while calling the given function. - """ - self._state_tracker.Reset() - while token: - if debug_tokens: - print token - - if parse_error and parse_error.token == token: - message = ('Error parsing file at token "%s". Unable to ' - 'check the rest of file.' % token.string) - self.HandleError(errors.FILE_DOES_NOT_PARSE, message, token) - self._error_handler.FinishFile() - return - - try: - self._state_tracker.HandleToken( - token, self._state_tracker.GetLastNonSpaceToken()) - pass_function(token) - self._state_tracker.HandleAfterToken(token) - except: - if FLAGS.error_trace: - raise - else: - self.HandleError(errors.FILE_DOES_NOT_PARSE, - ('Error parsing file at token "%s". Unable to ' - 'check the rest of file.' % token.string), - token) - self._error_handler.FinishFile() - return False - token = token.next - return True diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/closurizednamespacesinfo.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/closurizednamespacesinfo.py deleted file mode 100755 index f2902dc3..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/closurizednamespacesinfo.py +++ /dev/null @@ -1,500 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Logic for computing dependency information for closurized JavaScript files. - -Closurized JavaScript files express dependencies using goog.require and -goog.provide statements. In order for the linter to detect when a statement is -missing or unnecessary, all identifiers in the JavaScript file must first be -processed to determine if they constitute the creation or usage of a dependency. -""" - - - -from closure_linter import javascripttokens -from closure_linter import tokenutil - -# pylint: disable-msg=C6409 -TokenType = javascripttokens.JavaScriptTokenType - -DEFAULT_EXTRA_NAMESPACES = [ - 'goog.testing.asserts', - 'goog.testing.jsunit', -] - -class ClosurizedNamespacesInfo(object): - """Dependency information for closurized JavaScript files. - - Processes token streams for dependency creation or usage and provides logic - for determining if a given require or provide statement is unnecessary or if - there are missing require or provide statements. - """ - - def __init__(self, closurized_namespaces, ignored_extra_namespaces): - """Initializes an instance the ClosurizedNamespacesInfo class. - - Args: - closurized_namespaces: A list of namespace prefixes that should be - processed for dependency information. Non-matching namespaces are - ignored. - ignored_extra_namespaces: A list of namespaces that should not be reported - as extra regardless of whether they are actually used. - """ - self._closurized_namespaces = closurized_namespaces - self._ignored_extra_namespaces = (ignored_extra_namespaces + - DEFAULT_EXTRA_NAMESPACES) - self.Reset() - - def Reset(self): - """Resets the internal state to prepare for processing a new file.""" - - # A list of goog.provide tokens in the order they appeared in the file. - self._provide_tokens = [] - - # A list of goog.require tokens in the order they appeared in the file. - self._require_tokens = [] - - # Namespaces that are already goog.provided. - self._provided_namespaces = [] - - # Namespaces that are already goog.required. - self._required_namespaces = [] - - # Note that created_namespaces and used_namespaces contain both namespaces - # and identifiers because there are many existing cases where a method or - # constant is provided directly instead of its namespace. Ideally, these - # two lists would only have to contain namespaces. - - # A list of tuples where the first element is the namespace of an identifier - # created in the file and the second is the identifier itself. - self._created_namespaces = [] - - # A list of tuples where the first element is the namespace of an identifier - # used in the file and the second is the identifier itself. - self._used_namespaces = [] - - # A list of seemingly-unnecessary namespaces that are goog.required() and - # annotated with @suppress {extraRequire}. - self._suppressed_requires = [] - - # A list of goog.provide tokens which are duplicates. - self._duplicate_provide_tokens = [] - - # A list of goog.require tokens which are duplicates. - self._duplicate_require_tokens = [] - - # Whether this file is in a goog.scope. Someday, we may add support - # for checking scopified namespaces, but for now let's just fail - # in a more reasonable way. - self._scopified_file = False - - # TODO(user): Handle the case where there are 2 different requires - # that can satisfy the same dependency, but only one is necessary. - - def GetProvidedNamespaces(self): - """Returns the namespaces which are already provided by this file. - - Returns: - A list of strings where each string is a 'namespace' corresponding to an - existing goog.provide statement in the file being checked. - """ - return list(self._provided_namespaces) - - def GetRequiredNamespaces(self): - """Returns the namespaces which are already required by this file. - - Returns: - A list of strings where each string is a 'namespace' corresponding to an - existing goog.require statement in the file being checked. - """ - return list(self._required_namespaces) - - def IsExtraProvide(self, token): - """Returns whether the given goog.provide token is unnecessary. - - Args: - token: A goog.provide token. - - Returns: - True if the given token corresponds to an unnecessary goog.provide - statement, otherwise False. - """ - if self._scopified_file: - return False - - namespace = tokenutil.Search(token, TokenType.STRING_TEXT).string - - base_namespace = namespace.split('.', 1)[0] - if base_namespace not in self._closurized_namespaces: - return False - - if token in self._duplicate_provide_tokens: - return True - - # TODO(user): There's probably a faster way to compute this. - for created_namespace, created_identifier in self._created_namespaces: - if namespace == created_namespace or namespace == created_identifier: - return False - - return True - - def IsExtraRequire(self, token): - """Returns whether the given goog.require token is unnecessary. - - Args: - token: A goog.require token. - - Returns: - True if the given token corresponds to an unnecessary goog.require - statement, otherwise False. - """ - if self._scopified_file: - return False - - namespace = tokenutil.Search(token, TokenType.STRING_TEXT).string - - base_namespace = namespace.split('.', 1)[0] - if base_namespace not in self._closurized_namespaces: - return False - - if namespace in self._ignored_extra_namespaces: - return False - - if token in self._duplicate_require_tokens: - return True - - if namespace in self._suppressed_requires: - return False - - # If the namespace contains a component that is initial caps, then that - # must be the last component of the namespace. - parts = namespace.split('.') - if len(parts) > 1 and parts[-2][0].isupper(): - return True - - # TODO(user): There's probably a faster way to compute this. - for used_namespace, used_identifier in self._used_namespaces: - if namespace == used_namespace or namespace == used_identifier: - return False - - return True - - def GetMissingProvides(self): - """Returns the set of missing provided namespaces for the current file. - - Returns: - Returns a set of strings where each string is a namespace that should be - provided by this file, but is not. - """ - if self._scopified_file: - return set() - - missing_provides = set() - for namespace, identifier in self._created_namespaces: - if (not self._IsPrivateIdentifier(identifier) and - namespace not in self._provided_namespaces and - identifier not in self._provided_namespaces and - namespace not in self._required_namespaces): - missing_provides.add(namespace) - - return missing_provides - - def GetMissingRequires(self): - """Returns the set of missing required namespaces for the current file. - - For each non-private identifier used in the file, find either a - goog.require, goog.provide or a created identifier that satisfies it. - goog.require statements can satisfy the identifier by requiring either the - namespace of the identifier or the identifier itself. goog.provide - statements can satisfy the identifier by providing the namespace of the - identifier. A created identifier can only satisfy the used identifier if - it matches it exactly (necessary since things can be defined on a - namespace in more than one file). Note that provided namespaces should be - a subset of created namespaces, but we check both because in some cases we - can't always detect the creation of the namespace. - - Returns: - Returns a set of strings where each string is a namespace that should be - required by this file, but is not. - """ - if self._scopified_file: - return set() - - external_dependencies = set(self._required_namespaces) - - # Assume goog namespace is always available. - external_dependencies.add('goog') - - created_identifiers = set() - for namespace, identifier in self._created_namespaces: - created_identifiers.add(identifier) - - missing_requires = set() - for namespace, identifier in self._used_namespaces: - if (not self._IsPrivateIdentifier(identifier) and - namespace not in external_dependencies and - namespace not in self._provided_namespaces and - identifier not in external_dependencies and - identifier not in created_identifiers): - missing_requires.add(namespace) - - return missing_requires - - def _IsPrivateIdentifier(self, identifier): - """Returns whether the given identifer is private.""" - pieces = identifier.split('.') - for piece in pieces: - if piece.endswith('_'): - return True - return False - - def IsFirstProvide(self, token): - """Returns whether token is the first provide token.""" - return self._provide_tokens and token == self._provide_tokens[0] - - def IsFirstRequire(self, token): - """Returns whether token is the first require token.""" - return self._require_tokens and token == self._require_tokens[0] - - def IsLastProvide(self, token): - """Returns whether token is the last provide token.""" - return self._provide_tokens and token == self._provide_tokens[-1] - - def IsLastRequire(self, token): - """Returns whether token is the last require token.""" - return self._require_tokens and token == self._require_tokens[-1] - - def ProcessToken(self, token, state_tracker): - """Processes the given token for dependency information. - - Args: - token: The token to process. - state_tracker: The JavaScript state tracker. - """ - - # Note that this method is in the critical path for the linter and has been - # optimized for performance in the following ways: - # - Tokens are checked by type first to minimize the number of function - # calls necessary to determine if action needs to be taken for the token. - # - The most common tokens types are checked for first. - # - The number of function calls has been minimized (thus the length of this - # function. - - if token.type == TokenType.IDENTIFIER: - # TODO(user): Consider saving the whole identifier in metadata. - whole_identifier_string = self._GetWholeIdentifierString(token) - if whole_identifier_string is None: - # We only want to process the identifier one time. If the whole string - # identifier is None, that means this token was part of a multi-token - # identifier, but it was not the first token of the identifier. - return - - # In the odd case that a goog.require is encountered inside a function, - # just ignore it (e.g. dynamic loading in test runners). - if token.string == 'goog.require' and not state_tracker.InFunction(): - self._require_tokens.append(token) - namespace = tokenutil.Search(token, TokenType.STRING_TEXT).string - if namespace in self._required_namespaces: - self._duplicate_require_tokens.append(token) - else: - self._required_namespaces.append(namespace) - - # If there is a suppression for the require, add a usage for it so it - # gets treated as a regular goog.require (i.e. still gets sorted). - jsdoc = state_tracker.GetDocComment() - if jsdoc and ('extraRequire' in jsdoc.suppressions): - self._suppressed_requires.append(namespace) - self._AddUsedNamespace(state_tracker, namespace) - - elif token.string == 'goog.provide': - self._provide_tokens.append(token) - namespace = tokenutil.Search(token, TokenType.STRING_TEXT).string - if namespace in self._provided_namespaces: - self._duplicate_provide_tokens.append(token) - else: - self._provided_namespaces.append(namespace) - - # If there is a suppression for the provide, add a creation for it so it - # gets treated as a regular goog.provide (i.e. still gets sorted). - jsdoc = state_tracker.GetDocComment() - if jsdoc and ('extraProvide' in jsdoc.suppressions): - self._AddCreatedNamespace(state_tracker, namespace) - - elif token.string == 'goog.scope': - self._scopified_file = True - - else: - jsdoc = state_tracker.GetDocComment() - if jsdoc and jsdoc.HasFlag('typedef'): - self._AddCreatedNamespace(state_tracker, whole_identifier_string, - self.GetClosurizedNamespace( - whole_identifier_string)) - else: - self._AddUsedNamespace(state_tracker, whole_identifier_string) - - elif token.type == TokenType.SIMPLE_LVALUE: - identifier = token.values['identifier'] - namespace = self.GetClosurizedNamespace(identifier) - if state_tracker.InFunction(): - self._AddUsedNamespace(state_tracker, identifier) - elif namespace and namespace != 'goog': - self._AddCreatedNamespace(state_tracker, identifier, namespace) - - elif token.type == TokenType.DOC_FLAG: - flag_type = token.attached_object.flag_type - is_interface = state_tracker.GetDocComment().HasFlag('interface') - if flag_type == 'implements' or (flag_type == 'extends' and is_interface): - # Interfaces should be goog.require'd. - doc_start = tokenutil.Search(token, TokenType.DOC_START_BRACE) - interface = tokenutil.Search(doc_start, TokenType.COMMENT) - self._AddUsedNamespace(state_tracker, interface.string) - - - def _GetWholeIdentifierString(self, token): - """Returns the whole identifier string for the given token. - - Checks the tokens after the current one to see if the token is one in a - sequence of tokens which are actually just one identifier (i.e. a line was - wrapped in the middle of an identifier). - - Args: - token: The token to check. - - Returns: - The whole identifier string or None if this token is not the first token - in a multi-token identifier. - """ - result = '' - - # Search backward to determine if this token is the first token of the - # identifier. If it is not the first token, return None to signal that this - # token should be ignored. - prev_token = token.previous - while prev_token: - if (prev_token.IsType(TokenType.IDENTIFIER) or - prev_token.IsType(TokenType.NORMAL) and prev_token.string == '.'): - return None - elif (not prev_token.IsType(TokenType.WHITESPACE) and - not prev_token.IsAnyType(TokenType.COMMENT_TYPES)): - break - prev_token = prev_token.previous - - # Search forward to find other parts of this identifier separated by white - # space. - next_token = token - while next_token: - if (next_token.IsType(TokenType.IDENTIFIER) or - next_token.IsType(TokenType.NORMAL) and next_token.string == '.'): - result += next_token.string - elif (not next_token.IsType(TokenType.WHITESPACE) and - not next_token.IsAnyType(TokenType.COMMENT_TYPES)): - break - next_token = next_token.next - - return result - - def _AddCreatedNamespace(self, state_tracker, identifier, namespace=None): - """Adds the namespace of an identifier to the list of created namespaces. - - If the identifier is annotated with a 'missingProvide' suppression, it is - not added. - - Args: - state_tracker: The JavaScriptStateTracker instance. - identifier: The identifier to add. - namespace: The namespace of the identifier or None if the identifier is - also the namespace. - """ - if not namespace: - namespace = identifier - - jsdoc = state_tracker.GetDocComment() - if jsdoc and 'missingProvide' in jsdoc.suppressions: - return - - self._created_namespaces.append([namespace, identifier]) - - def _AddUsedNamespace(self, state_tracker, identifier): - """Adds the namespace of an identifier to the list of used namespaces. - - If the identifier is annotated with a 'missingRequire' suppression, it is - not added. - - Args: - state_tracker: The JavaScriptStateTracker instance. - identifier: An identifier which has been used. - """ - jsdoc = state_tracker.GetDocComment() - if jsdoc and 'missingRequire' in jsdoc.suppressions: - return - - namespace = self.GetClosurizedNamespace(identifier) - if namespace: - self._used_namespaces.append([namespace, identifier]) - - def GetClosurizedNamespace(self, identifier): - """Given an identifier, returns the namespace that identifier is from. - - Args: - identifier: The identifier to extract a namespace from. - - Returns: - The namespace the given identifier resides in, or None if one could not - be found. - """ - if identifier.startswith('goog.global'): - # Ignore goog.global, since it is, by definition, global. - return None - - parts = identifier.split('.') - for namespace in self._closurized_namespaces: - if not identifier.startswith(namespace + '.'): - continue - - last_part = parts[-1] - if not last_part: - # TODO(robbyw): Handle this: it's a multi-line identifier. - return None - - # The namespace for a class is the shortest prefix ending in a class - # name, which starts with a capital letter but is not a capitalized word. - # - # We ultimately do not want to allow requiring or providing of inner - # classes/enums. Instead, a file should provide only the top-level class - # and users should require only that. - namespace = [] - for part in parts: - if part == 'prototype' or part.isupper(): - return '.'.join(namespace) - namespace.append(part) - if part[0].isupper(): - return '.'.join(namespace) - - # At this point, we know there's no class or enum, so the namespace is - # just the identifier with the last part removed. With the exception of - # apply, inherits, and call, which should also be stripped. - if parts[-1] in ('apply', 'inherits', 'call'): - parts.pop() - parts.pop() - - # If the last part ends with an underscore, it is a private variable, - # method, or enum. The namespace is whatever is before it. - if parts and parts[-1].endswith('_'): - parts.pop() - - return '.'.join(parts) - - return None diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py deleted file mode 100755 index cec3376e..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py +++ /dev/null @@ -1,451 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Unit tests for ClosurizedNamespacesInfo.""" - - - -import unittest as googletest -from closure_linter import closurizednamespacesinfo -from closure_linter import javascriptstatetracker -from closure_linter import javascripttokenizer -from closure_linter import javascripttokens -from closure_linter import tokenutil - -# pylint: disable-msg=C6409 -TokenType = javascripttokens.JavaScriptTokenType - - -class ClosurizedNamespacesInfoTest(googletest.TestCase): - """Tests for ClosurizedNamespacesInfo.""" - - _test_cases = { - 'goog.global.anything': None, - 'package.CONSTANT': 'package', - 'package.methodName': 'package', - 'package.subpackage.methodName': 'package.subpackage', - 'package.subpackage.methodName.apply': 'package.subpackage', - 'package.ClassName.something': 'package.ClassName', - 'package.ClassName.Enum.VALUE.methodName': 'package.ClassName', - 'package.ClassName.CONSTANT': 'package.ClassName', - 'package.namespace.CONSTANT.methodName': 'package.namespace', - 'package.ClassName.inherits': 'package.ClassName', - 'package.ClassName.apply': 'package.ClassName', - 'package.ClassName.methodName.apply': 'package.ClassName', - 'package.ClassName.methodName.call': 'package.ClassName', - 'package.ClassName.prototype.methodName': 'package.ClassName', - 'package.ClassName.privateMethod_': 'package.ClassName', - 'package.className.privateProperty_': 'package.className', - 'package.className.privateProperty_.methodName': 'package.className', - 'package.ClassName.PrivateEnum_': 'package.ClassName', - 'package.ClassName.prototype.methodName.apply': 'package.ClassName', - 'package.ClassName.property.subProperty': 'package.ClassName', - 'package.className.prototype.something.somethingElse': 'package.className' - } - - _tokenizer = javascripttokenizer.JavaScriptTokenizer() - - def testGetClosurizedNamespace(self): - """Tests that the correct namespace is returned for various identifiers.""" - namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( - closurized_namespaces=['package'], ignored_extra_namespaces=[]) - for identifier, expected_namespace in self._test_cases.items(): - actual_namespace = namespaces_info.GetClosurizedNamespace(identifier) - self.assertEqual( - expected_namespace, - actual_namespace, - 'expected namespace "' + str(expected_namespace) + - '" for identifier "' + str(identifier) + '" but was "' + - str(actual_namespace) + '"') - - def testIgnoredExtraNamespaces(self): - """Tests that ignored_extra_namespaces are ignored.""" - token = self._GetRequireTokens('package.Something') - namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( - closurized_namespaces=['package'], - ignored_extra_namespaces=['package.Something']) - - self.assertFalse(namespaces_info.IsExtraRequire(token), - 'Should be valid since it is in ignored namespaces.') - - namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( - ['package'], []) - - self.assertTrue(namespaces_info.IsExtraRequire(token), - 'Should be invalid since it is not in ignored namespaces.') - - def testIsExtraProvide_created(self): - """Tests that provides for created namespaces are not extra.""" - input_lines = [ - 'goog.provide(\'package.Foo\');', - 'package.Foo = function() {};' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraProvide(token), - 'Should not be extra since it is created.') - - def testIsExtraProvide_createdIdentifier(self): - """Tests that provides for created identifiers are not extra.""" - input_lines = [ - 'goog.provide(\'package.Foo.methodName\');', - 'package.Foo.methodName = function() {};' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraProvide(token), - 'Should not be extra since it is created.') - - def testIsExtraProvide_notCreated(self): - """Tests that provides for non-created namespaces are extra.""" - input_lines = ['goog.provide(\'package.Foo\');'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertTrue(namespaces_info.IsExtraProvide(token), - 'Should be extra since it is not created.') - - def testIsExtraProvide_duplicate(self): - """Tests that providing a namespace twice makes the second one extra.""" - input_lines = [ - 'goog.provide(\'package.Foo\');', - 'goog.provide(\'package.Foo\');', - 'package.Foo = function() {};' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - # Advance to the second goog.provide token. - token = tokenutil.Search(token.next, TokenType.IDENTIFIER) - - self.assertTrue(namespaces_info.IsExtraProvide(token), - 'Should be extra since it is already provided.') - - def testIsExtraProvide_notClosurized(self): - """Tests that provides of non-closurized namespaces are not extra.""" - input_lines = ['goog.provide(\'notclosurized.Foo\');'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraProvide(token), - 'Should not be extra since it is not closurized.') - - def testIsExtraRequire_used(self): - """Tests that requires for used namespaces are not extra.""" - input_lines = [ - 'goog.require(\'package.Foo\');', - 'var x = package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraRequire(token), - 'Should not be extra since it is used.') - - def testIsExtraRequire_usedIdentifier(self): - """Tests that requires for used methods on classes are extra.""" - input_lines = [ - 'goog.require(\'package.Foo.methodName\');', - 'var x = package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertTrue(namespaces_info.IsExtraRequire(token), - 'Should require the package, not the method specifically.') - - def testIsExtraRequire_notUsed(self): - """Tests that requires for unused namespaces are extra.""" - input_lines = ['goog.require(\'package.Foo\');'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertTrue(namespaces_info.IsExtraRequire(token), - 'Should be extra since it is not used.') - - def testIsExtraRequire_notClosurized(self): - """Tests that requires of non-closurized namespaces are not extra.""" - input_lines = ['goog.require(\'notclosurized.Foo\');'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraRequire(token), - 'Should not be extra since it is not closurized.') - - def testIsExtraRequire_objectOnClass(self): - """Tests that requiring an object on a class is extra.""" - input_lines = [ - 'goog.require(\'package.Foo.Enum\');', - 'var x = package.Foo.Enum.VALUE1;', - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertTrue(namespaces_info.IsExtraRequire(token), - 'The whole class, not the object, should be required.'); - - def testIsExtraRequire_constantOnClass(self): - """Tests that requiring a constant on a class is extra.""" - input_lines = [ - 'goog.require(\'package.Foo.CONSTANT\');', - 'var x = package.Foo.CONSTANT', - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertTrue(namespaces_info.IsExtraRequire(token), - 'The class, not the constant, should be required.'); - - def testIsExtraRequire_constantNotOnClass(self): - """Tests that requiring a constant not on a class is OK.""" - input_lines = [ - 'goog.require(\'package.subpackage.CONSTANT\');', - 'var x = package.subpackage.CONSTANT', - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraRequire(token), - 'Constants can be required except on classes.'); - - def testIsExtraRequire_methodNotOnClass(self): - """Tests that requiring a method not on a class is OK.""" - input_lines = [ - 'goog.require(\'package.subpackage.method\');', - 'var x = package.subpackage.method()', - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertFalse(namespaces_info.IsExtraRequire(token), - 'Methods can be required except on classes.'); - - def testIsExtraRequire_defaults(self): - """Tests that there are no warnings about extra requires for test utils""" - input_lines = ['goog.require(\'goog.testing.jsunit\');'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['goog'], []) - - self.assertFalse(namespaces_info.IsExtraRequire(token), - 'Should not be extra since it is for testing.') - - def testGetMissingProvides_provided(self): - """Tests that provided functions don't cause a missing provide.""" - input_lines = [ - 'goog.provide(\'package.Foo\');', - 'package.Foo = function() {};' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingProvides_providedIdentifier(self): - """Tests that provided identifiers don't cause a missing provide.""" - input_lines = [ - 'goog.provide(\'package.Foo.methodName\');', - 'package.Foo.methodName = function() {};' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingProvides_providedParentIdentifier(self): - """Tests that provided identifiers on a class don't cause a missing provide - on objects attached to that class.""" - input_lines = [ - 'goog.provide(\'package.foo.ClassName\');', - 'package.foo.ClassName.methodName = function() {};', - 'package.foo.ClassName.ObjectName = 1;', - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingProvides_unprovided(self): - """Tests that unprovided functions cause a missing provide.""" - input_lines = ['package.Foo = function() {};'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(1, len(namespaces_info.GetMissingProvides())) - self.assertTrue('package.Foo' in namespaces_info.GetMissingProvides()) - - def testGetMissingProvides_privatefunction(self): - """Tests that unprovided private functions don't cause a missing provide.""" - input_lines = ['package.Foo_ = function() {};'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingProvides_required(self): - """Tests that required namespaces don't cause a missing provide.""" - input_lines = [ - 'goog.require(\'package.Foo\');', - 'package.Foo.methodName = function() {};' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingRequires_required(self): - """Tests that required namespaces don't cause a missing require.""" - input_lines = [ - 'goog.require(\'package.Foo\');', - 'package.Foo();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingRequires_requiredIdentifier(self): - """Tests that required namespaces satisfy identifiers on that namespace.""" - input_lines = [ - 'goog.require(\'package.Foo\');', - 'package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingProvides())) - - def testGetMissingRequires_requiredParentClass(self): - """Tests that requiring a parent class of an object is sufficient to prevent - a missing require on that object.""" - input_lines = [ - 'goog.require(\'package.Foo\');', - 'package.Foo.methodName();', - 'package.Foo.methodName(package.Foo.ObjectName);' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingRequires())) - - def testGetMissingRequires_unrequired(self): - """Tests that unrequired namespaces cause a missing require.""" - input_lines = ['package.Foo();'] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(1, len(namespaces_info.GetMissingRequires())) - self.assertTrue('package.Foo' in namespaces_info.GetMissingRequires()) - - def testGetMissingRequires_provided(self): - """Tests that provided namespaces satisfy identifiers on that namespace.""" - input_lines = [ - 'goog.provide(\'package.Foo\');', - 'package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingRequires())) - - def testGetMissingRequires_created(self): - """Tests that created namespaces do not satisfy usage of an identifier.""" - input_lines = [ - 'package.Foo = function();', - 'package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(1, len(namespaces_info.GetMissingRequires())) - self.assertTrue('package.Foo' in namespaces_info.GetMissingRequires()) - - def testGetMissingRequires_createdIdentifier(self): - """Tests that created identifiers satisfy usage of the identifier.""" - input_lines = [ - 'package.Foo.methodName = function();', - 'package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(0, len(namespaces_info.GetMissingRequires())) - - def testGetMissingRequires_objectOnClass(self): - """Tests that we should require a class, not the object on the class.""" - input_lines = [ - 'goog.require(\'package.Foo.Enum\');', - 'var x = package.Foo.Enum.VALUE1;', - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertEquals(1, len(namespaces_info.GetMissingRequires()), - 'The whole class, not the object, should be required.'); - - def testIsFirstProvide(self): - """Tests operation of the isFirstProvide method.""" - input_lines = [ - 'goog.provide(\'package.Foo\');', - 'package.Foo.methodName();' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) - - self.assertTrue(namespaces_info.IsFirstProvide(token)) - - def testGetWholeIdentifierString(self): - """Tests that created identifiers satisfy usage of the identifier.""" - input_lines = [ - 'package.Foo.', - ' veryLong.', - ' identifier;' - ] - token = self._tokenizer.TokenizeFile(input_lines) - namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo([], []) - - self.assertEquals('package.Foo.veryLong.identifier', - namespaces_info._GetWholeIdentifierString(token)) - self.assertEquals(None, - namespaces_info._GetWholeIdentifierString(token.next)) - - def _GetInitializedNamespacesInfo(self, token, closurized_namespaces, - ignored_extra_namespaces): - """Returns a namespaces info initialized with the given token stream.""" - namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( - closurized_namespaces=closurized_namespaces, - ignored_extra_namespaces=ignored_extra_namespaces) - state_tracker = javascriptstatetracker.JavaScriptStateTracker() - - while token: - namespaces_info.ProcessToken(token, state_tracker) - token = token.next - - return namespaces_info - - def _GetProvideTokens(self, namespace): - """Returns a list of tokens for a goog.require of the given namespace.""" - line_text = 'goog.require(\'' + namespace + '\');\n' - return javascripttokenizer.JavaScriptTokenizer().TokenizeFile([line_text]) - - def _GetRequireTokens(self, namespace): - """Returns a list of tokens for a goog.require of the given namespace.""" - line_text = 'goog.require(\'' + namespace + '\');\n' - return javascripttokenizer.JavaScriptTokenizer().TokenizeFile([line_text]) - -if __name__ == '__main__': - googletest.main() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/__init__.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/__init__.py deleted file mode 100755 index 57930436..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Package indicator for gjslint.common.""" diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/error.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/error.py deleted file mode 100755 index 0e3b4760..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/error.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Error object commonly used in linters.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -class Error(object): - """Object representing a style error.""" - - def __init__(self, code, message, token, position, fix_data): - """Initialize the error object. - - Args: - code: The numeric error code. - message: The error message string. - token: The tokens.Token where the error occurred. - position: The position of the error within the token. - fix_data: Data to be used in autofixing. Codes with fix_data are: - GOOG_REQUIRES_NOT_ALPHABETIZED - List of string value tokens that are - class names in goog.requires calls. - """ - self.code = code - self.message = message - self.token = token - self.position = position - if token: - self.start_index = token.start_index - else: - self.start_index = 0 - self.fix_data = fix_data - if self.position: - self.start_index += self.position.start - - def Compare(a, b): - """Compare two error objects, by source code order. - - Args: - a: First error object. - b: Second error object. - - Returns: - A Negative/0/Positive number when a is before/the same as/after b. - """ - line_diff = a.token.line_number - b.token.line_number - if line_diff: - return line_diff - - return a.start_index - b.start_index - Compare = staticmethod(Compare) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/erroraccumulator.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/erroraccumulator.py deleted file mode 100755 index 55844ba6..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/erroraccumulator.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Linter error handler class that accumulates an array of errors.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -from closure_linter.common import errorhandler - - -class ErrorAccumulator(errorhandler.ErrorHandler): - """Error handler object that accumulates errors in a list.""" - - def __init__(self): - self._errors = [] - - def HandleError(self, error): - """Append the error to the list. - - Args: - error: The error object - """ - self._errors.append(error) - - def GetErrors(self): - """Returns the accumulated errors. - - Returns: - A sequence of errors. - """ - return self._errors diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/errorhandler.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/errorhandler.py deleted file mode 100755 index 764d54d8..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/errorhandler.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Interface for a linter error handler. - -Error handlers aggregate a set of errors from multiple files and can optionally -perform some action based on the reported errors, for example, logging the error -or automatically fixing it. -""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -class ErrorHandler(object): - """Error handler interface.""" - - def __init__(self): - if self.__class__ == ErrorHandler: - raise NotImplementedError('class ErrorHandler is abstract') - - def HandleFile(self, filename, first_token): - """Notifies this ErrorHandler that subsequent errors are in filename. - - Args: - filename: The file being linted. - first_token: The first token of the file. - """ - - def HandleError(self, error): - """Append the error to the list. - - Args: - error: The error object - """ - - def FinishFile(self): - """Finishes handling the current file. - - Should be called after all errors in a file have been handled. - """ - - def GetErrors(self): - """Returns the accumulated errors. - - Returns: - A sequence of errors. - """ diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/erroroutput.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/erroroutput.py deleted file mode 100755 index 149738b5..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/erroroutput.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Utility functions to format errors.""" - - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)', - 'nnaze@google.com (Nathan Naze)') - - -def GetUnixErrorOutput(filename, error, new_error=False): - """Get a output line for an error in UNIX format.""" - - line = '' - - if error.token: - line = '%d' % error.token.line_number - - error_code = '%04d' % error.code - if new_error: - error_code = 'New Error ' + error_code - return '%s:%s:(%s) %s' % (filename, line, error_code, error.message) - - -def GetErrorOutput(error, new_error=False): - """Get a output line for an error in regular format.""" - - line = '' - if error.token: - line = 'Line %d, ' % error.token.line_number - - code = 'E:%04d' % error.code - - error_message = error.message - if new_error: - error_message = 'New Error ' + error_message - - return '%s%s: %s' % (line, code, error.message) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/filetestcase.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/filetestcase.py deleted file mode 100755 index 03b5ece0..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/filetestcase.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Test case that runs a checker on a file, matching errors against annotations. - -Runs the given checker on the given file, accumulating all errors. The list -of errors is then matched against those annotated in the file. Based heavily -on devtools/javascript/gpylint/full_test.py. -""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import re - -import unittest as googletest -from closure_linter.common import erroraccumulator - - -class AnnotatedFileTestCase(googletest.TestCase): - """Test case to run a linter against a single file.""" - - # Matches an all caps letters + underscores error identifer - _MESSAGE = {'msg': '[A-Z][A-Z_]+'} - # Matches a //, followed by an optional line number with a +/-, followed by a - # list of message IDs. Used to extract expected messages from testdata files. - # TODO(robbyw): Generalize to use different commenting patterns. - _EXPECTED_RE = re.compile(r'\s*//\s*(?:(?P[+-]?[0-9]+):)?' - r'\s*(?P%(msg)s(?:,\s*%(msg)s)*)' % _MESSAGE) - - def __init__(self, filename, runner, converter): - """Create a single file lint test case. - - Args: - filename: Filename to test. - runner: Object implementing the LintRunner interface that lints a file. - converter: Function taking an error string and returning an error code. - """ - - googletest.TestCase.__init__(self, 'runTest') - self._filename = filename - self._messages = [] - self._runner = runner - self._converter = converter - - def shortDescription(self): - """Provides a description for the test.""" - return 'Run linter on %s' % self._filename - - def runTest(self): - """Runs the test.""" - try: - filename = self._filename - stream = open(filename) - except IOError, ex: - raise IOError('Could not find testdata resource for %s: %s' % - (self._filename, ex)) - - expected = self._GetExpectedMessages(stream) - got = self._ProcessFileAndGetMessages(filename) - self.assertEqual(expected, got) - - def _GetExpectedMessages(self, stream): - """Parse a file and get a sorted list of expected messages.""" - messages = [] - for i, line in enumerate(stream): - match = self._EXPECTED_RE.search(line) - if match: - line = match.group('line') - msg_ids = match.group('msgs') - if line is None: - line = i + 1 - elif line.startswith('+') or line.startswith('-'): - line = i + 1 + int(line) - else: - line = int(line) - for msg_id in msg_ids.split(','): - # Ignore a spurious message from the license preamble. - if msg_id != 'WITHOUT': - messages.append((line, self._converter(msg_id.strip()))) - stream.seek(0) - messages.sort() - return messages - - def _ProcessFileAndGetMessages(self, filename): - """Trap gpylint's output parse it to get messages added.""" - errors = erroraccumulator.ErrorAccumulator() - self._runner.Run([filename], errors) - - errors = errors.GetErrors() - - # Convert to expected tuple format. - error_msgs = [(error.token.line_number, error.code) for error in errors] - error_msgs.sort() - return error_msgs diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/htmlutil.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/htmlutil.py deleted file mode 100755 index 26d44c59..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/htmlutil.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Utilities for dealing with HTML.""" - -__author__ = ('robbyw@google.com (Robert Walker)') - -import cStringIO -import formatter -import htmllib -import HTMLParser -import re - - -class ScriptExtractor(htmllib.HTMLParser): - """Subclass of HTMLParser that extracts script contents from an HTML file. - - Also inserts appropriate blank lines so that line numbers in the extracted - code match the line numbers in the original HTML. - """ - - def __init__(self): - """Initialize a ScriptExtractor.""" - htmllib.HTMLParser.__init__(self, formatter.NullFormatter()) - self._in_script = False - self._text = '' - - def start_script(self, attrs): - """Internal handler for the start of a script tag. - - Args: - attrs: The attributes of the script tag, as a list of tuples. - """ - for attribute in attrs: - if attribute[0].lower() == 'src': - # Skip script tags with a src specified. - return - self._in_script = True - - def end_script(self): - """Internal handler for the end of a script tag.""" - self._in_script = False - - def handle_data(self, data): - """Internal handler for character data. - - Args: - data: The character data from the HTML file. - """ - if self._in_script: - # If the last line contains whitespace only, i.e. is just there to - # properly align a tag, strip the whitespace. - if data.rstrip(' \t') != data.rstrip(' \t\n\r\f'): - data = data.rstrip(' \t') - self._text += data - else: - self._AppendNewlines(data) - - def handle_comment(self, data): - """Internal handler for HTML comments. - - Args: - data: The text of the comment. - """ - self._AppendNewlines(data) - - def _AppendNewlines(self, data): - """Count the number of newlines in the given string and append them. - - This ensures line numbers are correct for reported errors. - - Args: - data: The data to count newlines in. - """ - # We append 'x' to both sides of the string to ensure that splitlines - # gives us an accurate count. - for i in xrange(len(('x' + data + 'x').splitlines()) - 1): - self._text += '\n' - - def GetScriptLines(self): - """Return the extracted script lines. - - Returns: - The extracted script lines as a list of strings. - """ - return self._text.splitlines() - - -def GetScriptLines(f): - """Extract script tag contents from the given HTML file. - - Args: - f: The HTML file. - - Returns: - Lines in the HTML file that are from script tags. - """ - extractor = ScriptExtractor() - - # The HTML parser chokes on text like Array., so we patch - # that bug by replacing the < with < - escaping all text inside script - # tags would be better but it's a bit of a catch 22. - contents = f.read() - contents = re.sub(r'<([^\s\w/])', - lambda x: '<%s' % x.group(1), - contents) - - extractor.feed(contents) - extractor.close() - return extractor.GetScriptLines() - - -def StripTags(str): - """Returns the string with HTML tags stripped. - - Args: - str: An html string. - - Returns: - The html string with all tags stripped. If there was a parse error, returns - the text successfully parsed so far. - """ - # Brute force approach to stripping as much HTML as possible. If there is a - # parsing error, don't strip text before parse error position, and continue - # trying from there. - final_text = '' - finished = False - while not finished: - try: - strip = _HtmlStripper() - strip.feed(str) - strip.close() - str = strip.get_output() - final_text += str - finished = True - except HTMLParser.HTMLParseError, e: - final_text += str[:e.offset] - str = str[e.offset + 1:] - - return final_text - - -class _HtmlStripper(HTMLParser.HTMLParser): - """Simple class to strip tags from HTML. - - Does so by doing nothing when encountering tags, and appending character data - to a buffer when that is encountered. - """ - def __init__(self): - self.reset() - self.__output = cStringIO.StringIO() - - def handle_data(self, d): - self.__output.write(d) - - def get_output(self): - return self.__output.getvalue() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/lintrunner.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/lintrunner.py deleted file mode 100755 index 07842c7b..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/lintrunner.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Interface for a lint running wrapper.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -class LintRunner(object): - """Interface for a lint running wrapper.""" - - def __init__(self): - if self.__class__ == LintRunner: - raise NotImplementedError('class LintRunner is abstract') - - def Run(self, filenames, error_handler): - """Run a linter on the given filenames. - - Args: - filenames: The filenames to check - error_handler: An ErrorHandler object - - Returns: - The error handler, which may have been used to collect error info. - """ diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/matcher.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/matcher.py deleted file mode 100755 index 9b4402c6..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/matcher.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Regular expression based JavaScript matcher classes.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -from closure_linter.common import position -from closure_linter.common import tokens - -# Shorthand -Token = tokens.Token -Position = position.Position - - -class Matcher(object): - """A token matcher. - - Specifies a pattern to match, the type of token it represents, what mode the - token changes to, and what mode the token applies to. - - Modes allow more advanced grammars to be incorporated, and are also necessary - to tokenize line by line. We can have different patterns apply to different - modes - i.e. looking for documentation while in comment mode. - - Attributes: - regex: The regular expression representing this matcher. - type: The type of token indicated by a successful match. - result_mode: The mode to move to after a successful match. - """ - - def __init__(self, regex, token_type, result_mode=None, line_start=False): - """Create a new matcher template. - - Args: - regex: The regular expression to match. - token_type: The type of token a successful match indicates. - result_mode: What mode to change to after a successful match. Defaults to - None, which means to not change the current mode. - line_start: Whether this matcher should only match string at the start - of a line. - """ - self.regex = regex - self.type = token_type - self.result_mode = result_mode - self.line_start = line_start diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/position.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/position.py deleted file mode 100755 index cebf17ef..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/position.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Classes to represent positions within strings.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -class Position(object): - """Object representing a segment of a string. - - Attributes: - start: The index in to the string where the segment starts. - length: The length of the string segment. - """ - - def __init__(self, start, length): - """Initialize the position object. - - Args: - start: The start index. - length: The number of characters to include. - """ - self.start = start - self.length = length - - def Get(self, string): - """Returns this range of the given string. - - Args: - string: The string to slice. - - Returns: - The string within the range specified by this object. - """ - return string[self.start:self.start + self.length] - - def Set(self, target, source): - """Sets this range within the target string to the source string. - - Args: - target: The target string. - source: The source string. - - Returns: - The resulting string - """ - return target[:self.start] + source + target[self.start + self.length:] - - def AtEnd(string): - """Create a Position representing the end of the given string. - - Args: - string: The string to represent the end of. - - Returns: - The created Position object. - """ - return Position(len(string), 0) - AtEnd = staticmethod(AtEnd) - - def IsAtEnd(self, string): - """Returns whether this position is at the end of the given string. - - Args: - string: The string to test for the end of. - - Returns: - Whether this position is at the end of the given string. - """ - return self.start == len(string) and self.length == 0 - - def AtBeginning(): - """Create a Position representing the beginning of any string. - - Returns: - The created Position object. - """ - return Position(0, 0) - AtBeginning = staticmethod(AtBeginning) - - def IsAtBeginning(self): - """Returns whether this position is at the beginning of any string. - - Returns: - Whether this position is at the beginning of any string. - """ - return self.start == 0 and self.length == 0 - - def All(string): - """Create a Position representing the entire string. - - Args: - string: The string to represent the entirety of. - - Returns: - The created Position object. - """ - return Position(0, len(string)) - All = staticmethod(All) - - def Index(index): - """Returns a Position object for the specified index. - - Args: - index: The index to select, inclusively. - - Returns: - The created Position object. - """ - return Position(index, 1) - Index = staticmethod(Index) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/simplefileflags.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/simplefileflags.py deleted file mode 100755 index 3402bef3..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/simplefileflags.py +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Determines the list of files to be checked from command line arguments.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import glob -import os -import re - -import gflags as flags - - -FLAGS = flags.FLAGS - -flags.DEFINE_multistring( - 'recurse', - None, - 'Recurse in to the subdirectories of the given path', - short_name='r') -flags.DEFINE_list( - 'exclude_directories', - ('_demos'), - 'Exclude the specified directories (only applicable along with -r or ' - '--presubmit)', - short_name='e') -flags.DEFINE_list( - 'exclude_files', - ('deps.js'), - 'Exclude the specified files', - short_name='x') - - -def MatchesSuffixes(filename, suffixes): - """Returns whether the given filename matches one of the given suffixes. - - Args: - filename: Filename to check. - suffixes: Sequence of suffixes to check. - - Returns: - Whether the given filename matches one of the given suffixes. - """ - suffix = filename[filename.rfind('.'):] - return suffix in suffixes - - -def _GetUserSpecifiedFiles(argv, suffixes): - """Returns files to be linted, specified directly on the command line. - - Can handle the '*' wildcard in filenames, but no other wildcards. - - Args: - argv: Sequence of command line arguments. The second and following arguments - are assumed to be files that should be linted. - suffixes: Expected suffixes for the file type being checked. - - Returns: - A sequence of files to be linted. - """ - files = argv[1:] or [] - all_files = [] - lint_files = [] - - # Perform any necessary globs. - for f in files: - if f.find('*') != -1: - for result in glob.glob(f): - all_files.append(result) - else: - all_files.append(f) - - for f in all_files: - if MatchesSuffixes(f, suffixes): - lint_files.append(f) - return lint_files - - -def _GetRecursiveFiles(suffixes): - """Returns files to be checked specified by the --recurse flag. - - Args: - suffixes: Expected suffixes for the file type being checked. - - Returns: - A list of files to be checked. - """ - lint_files = [] - # Perform any request recursion - if FLAGS.recurse: - for start in FLAGS.recurse: - for root, subdirs, files in os.walk(start): - for f in files: - if MatchesSuffixes(f, suffixes): - lint_files.append(os.path.join(root, f)) - return lint_files - - -def GetAllSpecifiedFiles(argv, suffixes): - """Returns all files specified by the user on the commandline. - - Args: - argv: Sequence of command line arguments. The second and following arguments - are assumed to be files that should be linted. - suffixes: Expected suffixes for the file type - - Returns: - A list of all files specified directly or indirectly (via flags) on the - command line by the user. - """ - files = _GetUserSpecifiedFiles(argv, suffixes) - - if FLAGS.recurse: - files += _GetRecursiveFiles(suffixes) - - return FilterFiles(files) - - -def FilterFiles(files): - """Filters the list of files to be linted be removing any excluded files. - - Filters out files excluded using --exclude_files and --exclude_directories. - - Args: - files: Sequence of files that needs filtering. - - Returns: - Filtered list of files to be linted. - """ - num_files = len(files) - - ignore_dirs_regexs = [] - for ignore in FLAGS.exclude_directories: - ignore_dirs_regexs.append(re.compile(r'(^|[\\/])%s[\\/]' % ignore)) - - result_files = [] - for f in files: - add_file = True - for exclude in FLAGS.exclude_files: - if f.endswith('/' + exclude) or f == exclude: - add_file = False - break - for ignore in ignore_dirs_regexs: - if ignore.search(f): - # Break out of ignore loop so we don't add to - # filtered files. - add_file = False - break - if add_file: - # Convert everything to absolute paths so we can easily remove duplicates - # using a set. - result_files.append(os.path.abspath(f)) - - skipped = num_files - len(result_files) - if skipped: - print 'Skipping %d file(s).' % skipped - - return set(result_files) - - -def GetFileList(argv, file_type, suffixes): - """Parse the flags and return the list of files to check. - - Args: - argv: Sequence of command line arguments. - suffixes: Sequence of acceptable suffixes for the file type. - - Returns: - The list of files to check. - """ - return sorted(GetAllSpecifiedFiles(argv, suffixes)) - - -def IsEmptyArgumentList(argv): - return not (len(argv[1:]) or FLAGS.recurse) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokenizer.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokenizer.py deleted file mode 100755 index 0234720d..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokenizer.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Regular expression based lexer.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -from closure_linter.common import tokens - -# Shorthand -Type = tokens.TokenType - - -class Tokenizer(object): - """General purpose tokenizer. - - Attributes: - mode: The latest mode of the tokenizer. This allows patterns to distinguish - if they are mid-comment, mid-parameter list, etc. - matchers: Dictionary of modes to sequences of matchers that define the - patterns to check at any given time. - default_types: Dictionary of modes to types, defining what type to give - non-matched text when in the given mode. Defaults to Type.NORMAL. - """ - - def __init__(self, starting_mode, matchers, default_types): - """Initialize the tokenizer. - - Args: - starting_mode: Mode to start in. - matchers: Dictionary of modes to sequences of matchers that defines the - patterns to check at any given time. - default_types: Dictionary of modes to types, defining what type to give - non-matched text when in the given mode. Defaults to Type.NORMAL. - """ - self.__starting_mode = starting_mode - self.matchers = matchers - self.default_types = default_types - - def TokenizeFile(self, file): - """Tokenizes the given file. - - Args: - file: An iterable that yields one line of the file at a time. - - Returns: - The first token in the file - """ - # The current mode. - self.mode = self.__starting_mode - # The first token in the stream. - self.__first_token = None - # The last token added to the token stream. - self.__last_token = None - # The current line number. - self.__line_number = 0 - - for line in file: - self.__line_number += 1 - self.__TokenizeLine(line) - - return self.__first_token - - def _CreateToken(self, string, token_type, line, line_number, values=None): - """Creates a new Token object (or subclass). - - Args: - string: The string of input the token represents. - token_type: The type of token. - line: The text of the line this token is in. - line_number: The line number of the token. - values: A dict of named values within the token. For instance, a - function declaration may have a value called 'name' which captures the - name of the function. - - Returns: - The newly created Token object. - """ - return tokens.Token(string, token_type, line, line_number, values) - - def __TokenizeLine(self, line): - """Tokenizes the given line. - - Args: - line: The contents of the line. - """ - string = line.rstrip('\n\r\f') - line_number = self.__line_number - self.__start_index = 0 - - if not string: - self.__AddToken(self._CreateToken('', Type.BLANK_LINE, line, line_number)) - return - - normal_token = '' - index = 0 - while index < len(string): - for matcher in self.matchers[self.mode]: - if matcher.line_start and index > 0: - continue - - match = matcher.regex.match(string, index) - - if match: - if normal_token: - self.__AddToken( - self.__CreateNormalToken(self.mode, normal_token, line, - line_number)) - normal_token = '' - - # Add the match. - self.__AddToken(self._CreateToken(match.group(), matcher.type, line, - line_number, match.groupdict())) - - # Change the mode to the correct one for after this match. - self.mode = matcher.result_mode or self.mode - - # Shorten the string to be matched. - index = match.end() - - break - - else: - # If the for loop finishes naturally (i.e. no matches) we just add the - # first character to the string of consecutive non match characters. - # These will constitute a NORMAL token. - if string: - normal_token += string[index:index + 1] - index += 1 - - if normal_token: - self.__AddToken( - self.__CreateNormalToken(self.mode, normal_token, line, line_number)) - - def __CreateNormalToken(self, mode, string, line, line_number): - """Creates a normal token. - - Args: - mode: The current mode. - string: The string to tokenize. - line: The line of text. - line_number: The line number within the file. - - Returns: - A Token object, of the default type for the current mode. - """ - type = Type.NORMAL - if mode in self.default_types: - type = self.default_types[mode] - return self._CreateToken(string, type, line, line_number) - - def __AddToken(self, token): - """Add the given token to the token stream. - - Args: - token: The token to add. - """ - # Store the first token, or point the previous token to this one. - if not self.__first_token: - self.__first_token = token - else: - self.__last_token.next = token - - # Establish the doubly linked list - token.previous = self.__last_token - self.__last_token = token - - # Compute the character indices - token.start_index = self.__start_index - self.__start_index += token.length diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokens.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokens.py deleted file mode 100755 index 4c7d8183..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokens.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Classes to represent tokens and positions within them.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -class TokenType(object): - """Token types common to all languages.""" - NORMAL = 'normal' - WHITESPACE = 'whitespace' - BLANK_LINE = 'blank line' - - -class Token(object): - """Token class for intelligent text splitting. - - The token class represents a string of characters and an identifying type. - - Attributes: - type: The type of token. - string: The characters the token comprises. - length: The length of the token. - line: The text of the line the token is found in. - line_number: The number of the line the token is found in. - values: Dictionary of values returned from the tokens regex match. - previous: The token before this one. - next: The token after this one. - start_index: The character index in the line where this token starts. - attached_object: Object containing more information about this token. - metadata: Object containing metadata about this token. Must be added by - a separate metadata pass. - """ - - def __init__(self, string, token_type, line, line_number, values=None): - """Creates a new Token object. - - Args: - string: The string of input the token contains. - token_type: The type of token. - line: The text of the line this token is in. - line_number: The line number of the token. - values: A dict of named values within the token. For instance, a - function declaration may have a value called 'name' which captures the - name of the function. - """ - self.type = token_type - self.string = string - self.length = len(string) - self.line = line - self.line_number = line_number - self.values = values - - # These parts can only be computed when the file is fully tokenized - self.previous = None - self.next = None - self.start_index = None - - # This part is set in statetracker.py - # TODO(robbyw): Wrap this in to metadata - self.attached_object = None - - # This part is set in *metadatapass.py - self.metadata = None - - def IsFirstInLine(self): - """Tests if this token is the first token in its line. - - Returns: - Whether the token is the first token in its line. - """ - return not self.previous or self.previous.line_number != self.line_number - - def IsLastInLine(self): - """Tests if this token is the last token in its line. - - Returns: - Whether the token is the last token in its line. - """ - return not self.next or self.next.line_number != self.line_number - - def IsType(self, token_type): - """Tests if this token is of the given type. - - Args: - token_type: The type to test for. - - Returns: - True if the type of this token matches the type passed in. - """ - return self.type == token_type - - def IsAnyType(self, *token_types): - """Tests if this token is any of the given types. - - Args: - token_types: The types to check. Also accepts a single array. - - Returns: - True if the type of this token is any of the types passed in. - """ - if not isinstance(token_types[0], basestring): - return self.type in token_types[0] - else: - return self.type in token_types - - def __repr__(self): - return '' % (self.type, self.string, - self.values, self.line_number, - self.metadata) - - def __iter__(self): - """Returns a token iterator.""" - node = self - while node: - yield node - node = node.next - - def __reversed__(self): - """Returns a reverse-direction token iterator.""" - node = self - while node: - yield node - node = node.previous diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokens_test.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokens_test.py deleted file mode 100755 index 79ac0aec..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/common/tokens_test.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python -# Copyright 2011 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - - - - -import unittest as googletest -from closure_linter.common import tokens - - -def _CreateDummyToken(): - return tokens.Token('foo', None, 1, 1) - - -def _CreateDummyTokens(count): - dummy_tokens = [] - for _ in xrange(count): - dummy_tokens.append(_CreateDummyToken()) - return dummy_tokens - - -def _SetTokensAsNeighbors(neighbor_tokens): - for i in xrange(len(neighbor_tokens)): - prev_index = i - 1 - next_index = i + 1 - - if prev_index >= 0: - neighbor_tokens[i].previous = neighbor_tokens[prev_index] - - if next_index < len(neighbor_tokens): - neighbor_tokens[i].next = neighbor_tokens[next_index] - - -class TokensTest(googletest.TestCase): - - def testIsFirstInLine(self): - - # First token in file (has no previous). - self.assertTrue(_CreateDummyToken().IsFirstInLine()) - - a, b = _CreateDummyTokens(2) - _SetTokensAsNeighbors([a, b]) - - # Tokens on same line - a.line_number = 30 - b.line_number = 30 - - self.assertFalse(b.IsFirstInLine()) - - # Tokens on different lines - b.line_number = 31 - self.assertTrue(b.IsFirstInLine()) - - def testIsLastInLine(self): - # Last token in file (has no next). - self.assertTrue(_CreateDummyToken().IsLastInLine()) - - a, b = _CreateDummyTokens(2) - _SetTokensAsNeighbors([a, b]) - - # Tokens on same line - a.line_number = 30 - b.line_number = 30 - self.assertFalse(a.IsLastInLine()) - - b.line_number = 31 - self.assertTrue(a.IsLastInLine()) - - def testIsType(self): - a = tokens.Token('foo', 'fakeType1', 1, 1) - self.assertTrue(a.IsType('fakeType1')) - self.assertFalse(a.IsType('fakeType2')) - - def testIsAnyType(self): - a = tokens.Token('foo', 'fakeType1', 1, 1) - self.assertTrue(a.IsAnyType(['fakeType1', 'fakeType2'])) - self.assertFalse(a.IsAnyType(['fakeType3', 'fakeType4'])) - - def testRepr(self): - a = tokens.Token('foo', 'fakeType1', 1, 1) - self.assertEquals('', str(a)) - - def testIter(self): - dummy_tokens = _CreateDummyTokens(5) - _SetTokensAsNeighbors(dummy_tokens) - a, b, c, d, e = dummy_tokens - - i = iter(a) - self.assertListEqual([a, b, c, d, e], list(i)) - - def testReverseIter(self): - dummy_tokens = _CreateDummyTokens(5) - _SetTokensAsNeighbors(dummy_tokens) - a, b, c, d, e = dummy_tokens - - ri = reversed(e) - self.assertListEqual([e, d, c, b, a], list(ri)) - - -if __name__ == '__main__': - googletest.main() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/ecmalintrules.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/ecmalintrules.py deleted file mode 100755 index 263385f4..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/ecmalintrules.py +++ /dev/null @@ -1,786 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Core methods for checking EcmaScript files for common style guide violations. -""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)', - 'jacobr@google.com (Jacob Richman)') - -import re - -from closure_linter import checkerbase -from closure_linter import ecmametadatapass -from closure_linter import error_check -from closure_linter import errors -from closure_linter import indentation -from closure_linter import javascripttokens -from closure_linter import javascripttokenizer -from closure_linter import statetracker -from closure_linter import tokenutil -from closure_linter.common import error -from closure_linter.common import htmlutil -from closure_linter.common import lintrunner -from closure_linter.common import position -from closure_linter.common import tokens -import gflags as flags - -FLAGS = flags.FLAGS -flags.DEFINE_list('custom_jsdoc_tags', '', 'Extra jsdoc tags to allow') - -# TODO(robbyw): Check for extra parens on return statements -# TODO(robbyw): Check for 0px in strings -# TODO(robbyw): Ensure inline jsDoc is in {} -# TODO(robbyw): Check for valid JS types in parameter docs - -# Shorthand -Context = ecmametadatapass.EcmaContext -Error = error.Error -Modes = javascripttokenizer.JavaScriptModes -Position = position.Position -Rule = error_check.Rule -Type = javascripttokens.JavaScriptTokenType - -class EcmaScriptLintRules(checkerbase.LintRulesBase): - """EmcaScript lint style checking rules. - - Can be used to find common style errors in JavaScript, ActionScript and other - Ecma like scripting languages. Style checkers for Ecma scripting languages - should inherit from this style checker. - Please do not add any state to EcmaScriptLintRules or to any subclasses. - - All state should be added to the StateTracker subclass used for a particular - language. - """ - - # Static constants. - MAX_LINE_LENGTH = 80 - - MISSING_PARAMETER_SPACE = re.compile(r',\S') - - EXTRA_SPACE = re.compile('(\(\s|\s\))') - - ENDS_WITH_SPACE = re.compile('\s$') - - ILLEGAL_TAB = re.compile(r'\t') - - # Regex used to split up complex types to check for invalid use of ? and |. - TYPE_SPLIT = re.compile(r'[,<>()]') - - # Regex for form of author lines after the @author tag. - AUTHOR_SPEC = re.compile(r'(\s*)[^\s]+@[^(\s]+(\s*)\(.+\)') - - # Acceptable tokens to remove for line too long testing. - LONG_LINE_IGNORE = frozenset(['*', '//', '@see'] + - ['@%s' % tag for tag in statetracker.DocFlag.HAS_TYPE]) - - def __init__(self): - """Initialize this lint rule object.""" - checkerbase.LintRulesBase.__init__(self) - - def Initialize(self, checker, limited_doc_checks, is_html): - """Initialize this lint rule object before parsing a new file.""" - checkerbase.LintRulesBase.Initialize(self, checker, limited_doc_checks, - is_html) - self._indentation = indentation.IndentationRules() - - def HandleMissingParameterDoc(self, token, param_name): - """Handle errors associated with a parameter missing a @param tag.""" - raise TypeError('Abstract method HandleMissingParameterDoc not implemented') - - def _CheckLineLength(self, last_token, state): - """Checks whether the line is too long. - - Args: - last_token: The last token in the line. - """ - # Start from the last token so that we have the flag object attached to - # and DOC_FLAG tokens. - line_number = last_token.line_number - token = last_token - - # Build a representation of the string where spaces indicate potential - # line-break locations. - line = [] - while token and token.line_number == line_number: - if state.IsTypeToken(token): - line.insert(0, 'x' * len(token.string)) - elif token.type in (Type.IDENTIFIER, Type.NORMAL): - # Dots are acceptable places to wrap. - line.insert(0, token.string.replace('.', ' ')) - else: - line.insert(0, token.string) - token = token.previous - - line = ''.join(line) - line = line.rstrip('\n\r\f') - try: - length = len(unicode(line, 'utf-8')) - except: - # Unknown encoding. The line length may be wrong, as was originally the - # case for utf-8 (see bug 1735846). For now just accept the default - # length, but as we find problems we can either add test for other - # possible encodings or return without an error to protect against - # false positives at the cost of more false negatives. - length = len(line) - - if length > self.MAX_LINE_LENGTH: - - # If the line matches one of the exceptions, then it's ok. - for long_line_regexp in self.GetLongLineExceptions(): - if long_line_regexp.match(last_token.line): - return - - # If the line consists of only one "word", or multiple words but all - # except one are ignoreable, then it's ok. - parts = set(line.split()) - - # We allow two "words" (type and name) when the line contains @param - max = 1 - if '@param' in parts: - max = 2 - - # Custom tags like @requires may have url like descriptions, so ignore - # the tag, similar to how we handle @see. - custom_tags = set(['@%s' % f for f in FLAGS.custom_jsdoc_tags]) - if (len(parts.difference(self.LONG_LINE_IGNORE | custom_tags)) > max): - self._HandleError(errors.LINE_TOO_LONG, - 'Line too long (%d characters).' % len(line), last_token) - - def _CheckJsDocType(self, token): - """Checks the given type for style errors. - - Args: - token: The DOC_FLAG token for the flag whose type to check. - """ - flag = token.attached_object - type = flag.type - if type and type is not None and not type.isspace(): - pieces = self.TYPE_SPLIT.split(type) - if len(pieces) == 1 and type.count('|') == 1 and ( - type.endswith('|null') or type.startswith('null|')): - self._HandleError(errors.JSDOC_PREFER_QUESTION_TO_PIPE_NULL, - 'Prefer "?Type" to "Type|null": "%s"' % type, token) - - for p in pieces: - if p.count('|') and p.count('?'): - # TODO(robbyw): We should do actual parsing of JsDoc types. As is, - # this won't report an error for {number|Array.?}, etc. - self._HandleError(errors.JSDOC_ILLEGAL_QUESTION_WITH_PIPE, - 'JsDoc types cannot contain both "?" and "|": "%s"' % p, token) - - if error_check.ShouldCheck(Rule.BRACES_AROUND_TYPE) and ( - flag.type_start_token.type != Type.DOC_START_BRACE or - flag.type_end_token.type != Type.DOC_END_BRACE): - self._HandleError(errors.MISSING_BRACES_AROUND_TYPE, - 'Type must always be surrounded by curly braces.', token) - - def _CheckForMissingSpaceBeforeToken(self, token): - """Checks for a missing space at the beginning of a token. - - Reports a MISSING_SPACE error if the token does not begin with a space or - the previous token doesn't end with a space and the previous token is on the - same line as the token. - - Args: - token: The token being checked - """ - # TODO(user): Check if too many spaces? - if (len(token.string) == len(token.string.lstrip()) and - token.previous and token.line_number == token.previous.line_number and - len(token.previous.string) - len(token.previous.string.rstrip()) == 0): - self._HandleError( - errors.MISSING_SPACE, - 'Missing space before "%s"' % token.string, - token, - Position.AtBeginning()) - - def _ExpectSpaceBeforeOperator(self, token): - """Returns whether a space should appear before the given operator token. - - Args: - token: The operator token. - - Returns: - Whether there should be a space before the token. - """ - if token.string == ',' or token.metadata.IsUnaryPostOperator(): - return False - - # Colons should appear in labels, object literals, the case of a switch - # statement, and ternary operator. Only want a space in the case of the - # ternary operator. - if (token.string == ':' and - token.metadata.context.type in (Context.LITERAL_ELEMENT, - Context.CASE_BLOCK, - Context.STATEMENT)): - return False - - if token.metadata.IsUnaryOperator() and token.IsFirstInLine(): - return False - - return True - - def CheckToken(self, token, state): - """Checks a token, given the current parser_state, for warnings and errors. - - Args: - token: The current token under consideration - state: parser_state object that indicates the current state in the page - """ - # Store some convenience variables - first_in_line = token.IsFirstInLine() - last_in_line = token.IsLastInLine() - last_non_space_token = state.GetLastNonSpaceToken() - - type = token.type - - # Process the line change. - if not self._is_html and error_check.ShouldCheck(Rule.INDENTATION): - # TODO(robbyw): Support checking indentation in HTML files. - indentation_errors = self._indentation.CheckToken(token, state) - for indentation_error in indentation_errors: - self._HandleError(*indentation_error) - - if last_in_line: - self._CheckLineLength(token, state) - - if type == Type.PARAMETERS: - # Find missing spaces in parameter lists. - if self.MISSING_PARAMETER_SPACE.search(token.string): - self._HandleError(errors.MISSING_SPACE, 'Missing space after ","', - token) - - # Find extra spaces at the beginning of parameter lists. Make sure - # we aren't at the beginning of a continuing multi-line list. - if not first_in_line: - space_count = len(token.string) - len(token.string.lstrip()) - if space_count: - self._HandleError(errors.EXTRA_SPACE, 'Extra space after "("', - token, Position(0, space_count)) - - elif (type == Type.START_BLOCK and - token.metadata.context.type == Context.BLOCK): - self._CheckForMissingSpaceBeforeToken(token) - - elif type == Type.END_BLOCK: - # This check is for object literal end block tokens, but there is no need - # to test that condition since a comma at the end of any other kind of - # block is undoubtedly a parse error. - last_code = token.metadata.last_code - if last_code.IsOperator(','): - self._HandleError(errors.COMMA_AT_END_OF_LITERAL, - 'Illegal comma at end of object literal', last_code, - Position.All(last_code.string)) - - if state.InFunction() and state.IsFunctionClose(): - is_immediately_called = (token.next and - token.next.type == Type.START_PAREN) - if state.InTopLevelFunction(): - # When the function was top-level and not immediately called, check - # that it's terminated by a semi-colon. - if state.InAssignedFunction(): - if not is_immediately_called and (last_in_line or - not token.next.type == Type.SEMICOLON): - self._HandleError(errors.MISSING_SEMICOLON_AFTER_FUNCTION, - 'Missing semicolon after function assigned to a variable', - token, Position.AtEnd(token.string)) - else: - if not last_in_line and token.next.type == Type.SEMICOLON: - self._HandleError(errors.ILLEGAL_SEMICOLON_AFTER_FUNCTION, - 'Illegal semicolon after function declaration', - token.next, Position.All(token.next.string)) - - if (state.InInterfaceMethod() and last_code.type != Type.START_BLOCK): - self._HandleError(errors.INTERFACE_METHOD_CANNOT_HAVE_CODE, - 'Interface methods cannot contain code', last_code) - - elif (state.IsBlockClose() and - token.next and token.next.type == Type.SEMICOLON): - self._HandleError(errors.REDUNDANT_SEMICOLON, - 'No semicolon is required to end a code block', - token.next, Position.All(token.next.string)) - - elif type == Type.SEMICOLON: - if token.previous and token.previous.type == Type.WHITESPACE: - self._HandleError(errors.EXTRA_SPACE, 'Extra space before ";"', - token.previous, Position.All(token.previous.string)) - - if token.next and token.next.line_number == token.line_number: - if token.metadata.context.type != Context.FOR_GROUP_BLOCK: - # TODO(robbyw): Error about no multi-statement lines. - pass - - elif token.next.type not in ( - Type.WHITESPACE, Type.SEMICOLON, Type.END_PAREN): - self._HandleError(errors.MISSING_SPACE, - 'Missing space after ";" in for statement', - token.next, - Position.AtBeginning()) - - last_code = token.metadata.last_code - if last_code and last_code.type == Type.SEMICOLON: - # Allow a single double semi colon in for loops for cases like: - # for (;;) { }. - # NOTE(user): This is not a perfect check, and will not throw an error - # for cases like: for (var i = 0;; i < n; i++) {}, but then your code - # probably won't work either. - for_token = tokenutil.CustomSearch(last_code, - lambda token: token.type == Type.KEYWORD and token.string == 'for', - end_func=lambda token: token.type == Type.SEMICOLON, - distance=None, - reverse=True) - - if not for_token: - self._HandleError(errors.REDUNDANT_SEMICOLON, 'Redundant semicolon', - token, Position.All(token.string)) - - elif type == Type.START_PAREN: - if token.previous and token.previous.type == Type.KEYWORD: - self._HandleError(errors.MISSING_SPACE, 'Missing space before "("', - token, Position.AtBeginning()) - elif token.previous and token.previous.type == Type.WHITESPACE: - before_space = token.previous.previous - if (before_space and before_space.line_number == token.line_number and - before_space.type == Type.IDENTIFIER): - self._HandleError(errors.EXTRA_SPACE, 'Extra space before "("', - token.previous, Position.All(token.previous.string)) - - elif type == Type.START_BRACKET: - self._HandleStartBracket(token, last_non_space_token) - elif type in (Type.END_PAREN, Type.END_BRACKET): - # Ensure there is no space before closing parentheses, except when - # it's in a for statement with an omitted section, or when it's at the - # beginning of a line. - if (token.previous and token.previous.type == Type.WHITESPACE and - not token.previous.IsFirstInLine() and - not (last_non_space_token and last_non_space_token.line_number == - token.line_number and - last_non_space_token.type == Type.SEMICOLON)): - self._HandleError(errors.EXTRA_SPACE, 'Extra space before "%s"' % - token.string, token.previous, Position.All(token.previous.string)) - - if token.type == Type.END_BRACKET: - last_code = token.metadata.last_code - if last_code.IsOperator(','): - self._HandleError(errors.COMMA_AT_END_OF_LITERAL, - 'Illegal comma at end of array literal', last_code, - Position.All(last_code.string)) - - elif type == Type.WHITESPACE: - if self.ILLEGAL_TAB.search(token.string): - if token.IsFirstInLine(): - if token.next: - self._HandleError(errors.ILLEGAL_TAB, - 'Illegal tab in whitespace before "%s"' % token.next.string, - token, Position.All(token.string)) - else: - self._HandleError(errors.ILLEGAL_TAB, - 'Illegal tab in whitespace', - token, Position.All(token.string)) - else: - self._HandleError(errors.ILLEGAL_TAB, - 'Illegal tab in whitespace after "%s"' % token.previous.string, - token, Position.All(token.string)) - - # Check whitespace length if it's not the first token of the line and - # if it's not immediately before a comment. - if last_in_line: - # Check for extra whitespace at the end of a line. - self._HandleError(errors.EXTRA_SPACE, 'Extra space at end of line', - token, Position.All(token.string)) - elif not first_in_line and not token.next.IsComment(): - if token.length > 1: - self._HandleError(errors.EXTRA_SPACE, 'Extra space after "%s"' % - token.previous.string, token, - Position(1, len(token.string) - 1)) - - elif type == Type.OPERATOR: - last_code = token.metadata.last_code - - if not self._ExpectSpaceBeforeOperator(token): - if (token.previous and token.previous.type == Type.WHITESPACE and - last_code and last_code.type in (Type.NORMAL, Type.IDENTIFIER)): - self._HandleError(errors.EXTRA_SPACE, - 'Extra space before "%s"' % token.string, token.previous, - Position.All(token.previous.string)) - - elif (token.previous and - not token.previous.IsComment() and - token.previous.type in Type.EXPRESSION_ENDER_TYPES): - self._HandleError(errors.MISSING_SPACE, - 'Missing space before "%s"' % token.string, token, - Position.AtBeginning()) - - # Check that binary operators are not used to start lines. - if ((not last_code or last_code.line_number != token.line_number) and - not token.metadata.IsUnaryOperator()): - self._HandleError(errors.LINE_STARTS_WITH_OPERATOR, - 'Binary operator should go on previous line "%s"' % token.string, - token) - - elif type == Type.DOC_FLAG: - flag = token.attached_object - - if flag.flag_type == 'bug': - # TODO(robbyw): Check for exactly 1 space on the left. - string = token.next.string.lstrip() - string = string.split(' ', 1)[0] - - if not string.isdigit(): - self._HandleError(errors.NO_BUG_NUMBER_AFTER_BUG_TAG, - '@bug should be followed by a bug number', token) - - elif flag.flag_type == 'suppress': - if flag.type is None: - # A syntactically invalid suppress tag will get tokenized as a normal - # flag, indicating an error. - self._HandleError(errors.INCORRECT_SUPPRESS_SYNTAX, - 'Invalid suppress syntax: should be @suppress {errortype}. ' - 'Spaces matter.', token) - else: - for suppress_type in flag.type.split('|'): - if suppress_type not in state.GetDocFlag().SUPPRESS_TYPES: - self._HandleError(errors.INVALID_SUPPRESS_TYPE, - 'Invalid suppression type: %s' % suppress_type, - token) - - elif (error_check.ShouldCheck(Rule.WELL_FORMED_AUTHOR) and - flag.flag_type == 'author'): - # TODO(user): In non strict mode check the author tag for as much as - # it exists, though the full form checked below isn't required. - string = token.next.string - result = self.AUTHOR_SPEC.match(string) - if not result: - self._HandleError(errors.INVALID_AUTHOR_TAG_DESCRIPTION, - 'Author tag line should be of the form: ' - '@author foo@somewhere.com (Your Name)', - token.next) - else: - # Check spacing between email address and name. Do this before - # checking earlier spacing so positions are easier to calculate for - # autofixing. - num_spaces = len(result.group(2)) - if num_spaces < 1: - self._HandleError(errors.MISSING_SPACE, - 'Missing space after email address', - token.next, Position(result.start(2), 0)) - elif num_spaces > 1: - self._HandleError(errors.EXTRA_SPACE, - 'Extra space after email address', - token.next, - Position(result.start(2) + 1, num_spaces - 1)) - - # Check for extra spaces before email address. Can't be too few, if - # not at least one we wouldn't match @author tag. - num_spaces = len(result.group(1)) - if num_spaces > 1: - self._HandleError(errors.EXTRA_SPACE, - 'Extra space before email address', - token.next, Position(1, num_spaces - 1)) - - elif (flag.flag_type in state.GetDocFlag().HAS_DESCRIPTION and - not self._limited_doc_checks): - if flag.flag_type == 'param': - if flag.name is None: - self._HandleError(errors.MISSING_JSDOC_PARAM_NAME, - 'Missing name in @param tag', token) - - if not flag.description or flag.description is None: - flag_name = token.type - if 'name' in token.values: - flag_name = '@' + token.values['name'] - self._HandleError(errors.MISSING_JSDOC_TAG_DESCRIPTION, - 'Missing description in %s tag' % flag_name, token) - else: - self._CheckForMissingSpaceBeforeToken(flag.description_start_token) - - # We want punctuation to be inside of any tags ending a description, - # so strip tags before checking description. See bug 1127192. Note - # that depending on how lines break, the real description end token - # may consist only of stripped html and the effective end token can - # be different. - end_token = flag.description_end_token - end_string = htmlutil.StripTags(end_token.string).strip() - while (end_string == '' and not - end_token.type in Type.FLAG_ENDING_TYPES): - end_token = end_token.previous - if end_token.type in Type.FLAG_DESCRIPTION_TYPES: - end_string = htmlutil.StripTags(end_token.string).rstrip() - - if not (end_string.endswith('.') or end_string.endswith('?') or - end_string.endswith('!')): - # Find the position for the missing punctuation, inside of any html - # tags. - desc_str = end_token.string.rstrip() - while desc_str.endswith('>'): - start_tag_index = desc_str.rfind('<') - if start_tag_index < 0: - break - desc_str = desc_str[:start_tag_index].rstrip() - end_position = Position(len(desc_str), 0) - - self._HandleError( - errors.JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER, - ('%s descriptions must end with valid punctuation such as a ' - 'period.' % token.string), - end_token, end_position) - - if flag.flag_type in state.GetDocFlag().HAS_TYPE: - if flag.type_start_token is not None: - self._CheckForMissingSpaceBeforeToken( - token.attached_object.type_start_token) - - if flag.type and flag.type != '' and not flag.type.isspace(): - self._CheckJsDocType(token) - - if type in (Type.DOC_FLAG, Type.DOC_INLINE_FLAG): - if (token.values['name'] not in state.GetDocFlag().LEGAL_DOC and - token.values['name'] not in FLAGS.custom_jsdoc_tags): - self._HandleError(errors.INVALID_JSDOC_TAG, - 'Invalid JsDoc tag: %s' % token.values['name'], token) - - if (error_check.ShouldCheck(Rule.NO_BRACES_AROUND_INHERIT_DOC) and - token.values['name'] == 'inheritDoc' and - type == Type.DOC_INLINE_FLAG): - self._HandleError(errors.UNNECESSARY_BRACES_AROUND_INHERIT_DOC, - 'Unnecessary braces around @inheritDoc', - token) - - elif type == Type.SIMPLE_LVALUE: - identifier = token.values['identifier'] - - if ((not state.InFunction() or state.InConstructor()) and - not state.InParentheses() and not state.InObjectLiteralDescendant()): - jsdoc = state.GetDocComment() - if not state.HasDocComment(identifier): - # Only test for documentation on identifiers with .s in them to - # avoid checking things like simple variables. We don't require - # documenting assignments to .prototype itself (bug 1880803). - if (not state.InConstructor() and - identifier.find('.') != -1 and not - identifier.endswith('.prototype') and not - self._limited_doc_checks): - comment = state.GetLastComment() - if not (comment and comment.lower().count('jsdoc inherited')): - self._HandleError(errors.MISSING_MEMBER_DOCUMENTATION, - "No docs found for member '%s'" % identifier, - token); - elif jsdoc and (not state.InConstructor() or - identifier.startswith('this.')): - # We are at the top level and the function/member is documented. - if identifier.endswith('_') and not identifier.endswith('__'): - # Can have a private class which inherits documentation from a - # public superclass. - # - # @inheritDoc is deprecated in favor of using @override, and they - if (jsdoc.HasFlag('override') and not jsdoc.HasFlag('constructor') - and not ('accessControls' in jsdoc.suppressions)): - self._HandleError(errors.INVALID_OVERRIDE_PRIVATE, - '%s should not override a private member.' % identifier, - jsdoc.GetFlag('override').flag_token) - if (jsdoc.HasFlag('inheritDoc') and not jsdoc.HasFlag('constructor') - and not ('accessControls' in jsdoc.suppressions)): - self._HandleError(errors.INVALID_INHERIT_DOC_PRIVATE, - '%s should not inherit from a private member.' % identifier, - jsdoc.GetFlag('inheritDoc').flag_token) - if (not jsdoc.HasFlag('private') and - not ('underscore' in jsdoc.suppressions) and not - ((jsdoc.HasFlag('inheritDoc') or jsdoc.HasFlag('override')) and - ('accessControls' in jsdoc.suppressions))): - self._HandleError(errors.MISSING_PRIVATE, - 'Member "%s" must have @private JsDoc.' % - identifier, token) - if jsdoc.HasFlag('private') and 'underscore' in jsdoc.suppressions: - self._HandleError(errors.UNNECESSARY_SUPPRESS, - '@suppress {underscore} is not necessary with @private', - jsdoc.suppressions['underscore']) - elif (jsdoc.HasFlag('private') and - not self.InExplicitlyTypedLanguage()): - # It is convention to hide public fields in some ECMA - # implementations from documentation using the @private tag. - self._HandleError(errors.EXTRA_PRIVATE, - 'Member "%s" must not have @private JsDoc' % - identifier, token) - - # These flags are only legal on localizable message definitions; - # such variables always begin with the prefix MSG_. - for f in ('desc', 'hidden', 'meaning'): - if (jsdoc.HasFlag(f) - and not identifier.startswith('MSG_') - and identifier.find('.MSG_') == -1): - self._HandleError(errors.INVALID_USE_OF_DESC_TAG, - 'Member "%s" should not have @%s JsDoc' % (identifier, f), - token) - - # Check for illegaly assigning live objects as prototype property values. - index = identifier.find('.prototype.') - # Ignore anything with additional .s after the prototype. - if index != -1 and identifier.find('.', index + 11) == -1: - equal_operator = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES) - next_code = tokenutil.SearchExcept(equal_operator, Type.NON_CODE_TYPES) - if next_code and ( - next_code.type in (Type.START_BRACKET, Type.START_BLOCK) or - next_code.IsOperator('new')): - self._HandleError(errors.ILLEGAL_PROTOTYPE_MEMBER_VALUE, - 'Member %s cannot have a non-primitive value' % identifier, - token) - - elif type == Type.END_PARAMETERS: - # Find extra space at the end of parameter lists. We check the token - # prior to the current one when it is a closing paren. - if (token.previous and token.previous.type == Type.PARAMETERS - and self.ENDS_WITH_SPACE.search(token.previous.string)): - self._HandleError(errors.EXTRA_SPACE, 'Extra space before ")"', - token.previous) - - jsdoc = state.GetDocComment() - if state.GetFunction().is_interface: - if token.previous and token.previous.type == Type.PARAMETERS: - self._HandleError(errors.INTERFACE_CONSTRUCTOR_CANNOT_HAVE_PARAMS, - 'Interface constructor cannot have parameters', - token.previous) - elif (state.InTopLevel() and jsdoc and not jsdoc.HasFlag('see') - and not jsdoc.InheritsDocumentation() - and not state.InObjectLiteralDescendant() and not - jsdoc.IsInvalidated()): - distance, edit = jsdoc.CompareParameters(state.GetParams()) - if distance: - params_iter = iter(state.GetParams()) - docs_iter = iter(jsdoc.ordered_params) - - for op in edit: - if op == 'I': - # Insertion. - # Parsing doc comments is the same for all languages - # but some languages care about parameters that don't have - # doc comments and some languages don't care. - # Languages that don't allow variables to by typed such as - # JavaScript care but languages such as ActionScript or Java - # that allow variables to be typed don't care. - if not self._limited_doc_checks: - self.HandleMissingParameterDoc(token, params_iter.next()) - - elif op == 'D': - # Deletion - self._HandleError(errors.EXTRA_PARAMETER_DOCUMENTATION, - 'Found docs for non-existing parameter: "%s"' % - docs_iter.next(), token) - elif op == 'S': - # Substitution - if not self._limited_doc_checks: - self._HandleError(errors.WRONG_PARAMETER_DOCUMENTATION, - 'Parameter mismatch: got "%s", expected "%s"' % - (params_iter.next(), docs_iter.next()), token) - - else: - # Equality - just advance the iterators - params_iter.next() - docs_iter.next() - - elif type == Type.STRING_TEXT: - # If this is the first token after the start of the string, but it's at - # the end of a line, we know we have a multi-line string. - if token.previous.type in (Type.SINGLE_QUOTE_STRING_START, - Type.DOUBLE_QUOTE_STRING_START) and last_in_line: - self._HandleError(errors.MULTI_LINE_STRING, - 'Multi-line strings are not allowed', token) - - - # This check is orthogonal to the ones above, and repeats some types, so - # it is a plain if and not an elif. - if token.type in Type.COMMENT_TYPES: - if self.ILLEGAL_TAB.search(token.string): - self._HandleError(errors.ILLEGAL_TAB, - 'Illegal tab in comment "%s"' % token.string, token) - - trimmed = token.string.rstrip() - if last_in_line and token.string != trimmed: - # Check for extra whitespace at the end of a line. - self._HandleError(errors.EXTRA_SPACE, 'Extra space at end of line', - token, Position(len(trimmed), len(token.string) - len(trimmed))) - - # This check is also orthogonal since it is based on metadata. - if token.metadata.is_implied_semicolon: - self._HandleError(errors.MISSING_SEMICOLON, - 'Missing semicolon at end of line', token) - - def _HandleStartBracket(self, token, last_non_space_token): - """Handles a token that is an open bracket. - - Args: - token: The token to handle. - last_non_space_token: The last token that was not a space. - """ - if (not token.IsFirstInLine() and token.previous.type == Type.WHITESPACE and - last_non_space_token and - last_non_space_token.type in Type.EXPRESSION_ENDER_TYPES): - self._HandleError(errors.EXTRA_SPACE, 'Extra space before "["', - token.previous, Position.All(token.previous.string)) - # If the [ token is the first token in a line we shouldn't complain - # about a missing space before [. This is because some Ecma script - # languages allow syntax like: - # [Annotation] - # class MyClass {...} - # So we don't want to blindly warn about missing spaces before [. - # In the the future, when rules for computing exactly how many spaces - # lines should be indented are added, then we can return errors for - # [ tokens that are improperly indented. - # For example: - # var someVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVariableName = - # [a,b,c]; - # should trigger a proper indentation warning message as [ is not indented - # by four spaces. - elif (not token.IsFirstInLine() and token.previous and - not token.previous.type in ( - [Type.WHITESPACE, Type.START_PAREN, Type.START_BRACKET] + - Type.EXPRESSION_ENDER_TYPES)): - self._HandleError(errors.MISSING_SPACE, 'Missing space before "["', - token, Position.AtBeginning()) - - def Finalize(self, state, tokenizer_mode): - last_non_space_token = state.GetLastNonSpaceToken() - # Check last line for ending with newline. - if False and state.GetLastLine() and not (state.GetLastLine().isspace() or - state.GetLastLine().rstrip('\n\r\f') != state.GetLastLine()): - self._HandleError( - errors.FILE_MISSING_NEWLINE, - 'File does not end with new line. (%s)' % state.GetLastLine(), - last_non_space_token) - - # Check that the mode is not mid comment, argument list, etc. - if not tokenizer_mode == Modes.TEXT_MODE: - self._HandleError( - errors.FILE_IN_BLOCK, - 'File ended in mode "%s".' % tokenizer_mode, - last_non_space_token) - - try: - self._indentation.Finalize() - except Exception, e: - self._HandleError( - errors.FILE_DOES_NOT_PARSE, - str(e), - last_non_space_token) - - def GetLongLineExceptions(self): - """Gets a list of regexps for lines which can be longer than the limit.""" - return [] - - def InExplicitlyTypedLanguage(self): - """Returns whether this ecma implementation is explicitly typed.""" - return False diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/ecmametadatapass.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/ecmametadatapass.py deleted file mode 100755 index 2c797b3c..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/ecmametadatapass.py +++ /dev/null @@ -1,521 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Metadata pass for annotating tokens in EcmaScript files.""" - -__author__ = ('robbyw@google.com (Robert Walker)') - -from closure_linter import javascripttokens -from closure_linter import tokenutil - - -TokenType = javascripttokens.JavaScriptTokenType - - -class ParseError(Exception): - """Exception indicating a parse error at the given token. - - Attributes: - token: The token where the parse error occurred. - """ - - def __init__(self, token, message=None): - """Initialize a parse error at the given token with an optional message. - - Args: - token: The token where the parse error occurred. - message: A message describing the parse error. - """ - Exception.__init__(self, message) - self.token = token - - -class EcmaContext(object): - """Context object for EcmaScript languages. - - Attributes: - type: The context type. - start_token: The token where this context starts. - end_token: The token where this context ends. - parent: The parent context. - """ - - # The root context. - ROOT = 'root' - - # A block of code. - BLOCK = 'block' - - # A pseudo-block of code for a given case or default section. - CASE_BLOCK = 'case_block' - - # Block of statements in a for loop's parentheses. - FOR_GROUP_BLOCK = 'for_block' - - # An implied block of code for 1 line if, while, and for statements - IMPLIED_BLOCK = 'implied_block' - - # An index in to an array or object. - INDEX = 'index' - - # An array literal in []. - ARRAY_LITERAL = 'array_literal' - - # An object literal in {}. - OBJECT_LITERAL = 'object_literal' - - # An individual element in an array or object literal. - LITERAL_ELEMENT = 'literal_element' - - # The portion of a ternary statement between ? and : - TERNARY_TRUE = 'ternary_true' - - # The portion of a ternary statment after : - TERNARY_FALSE = 'ternary_false' - - # The entire switch statment. This will contain a GROUP with the variable - # and a BLOCK with the code. - - # Since that BLOCK is not a normal block, it can not contain statements except - # for case and default. - SWITCH = 'switch' - - # A normal comment. - COMMENT = 'comment' - - # A JsDoc comment. - DOC = 'doc' - - # An individual statement. - STATEMENT = 'statement' - - # Code within parentheses. - GROUP = 'group' - - # Parameter names in a function declaration. - PARAMETERS = 'parameters' - - # A set of variable declarations appearing after the 'var' keyword. - VAR = 'var' - - # Context types that are blocks. - BLOCK_TYPES = frozenset([ - ROOT, BLOCK, CASE_BLOCK, FOR_GROUP_BLOCK, IMPLIED_BLOCK]) - - def __init__(self, type, start_token, parent): - """Initializes the context object. - - Args: - type: The context type. - start_token: The token where this context starts. - parent: The parent context. - """ - self.type = type - self.start_token = start_token - self.end_token = None - self.parent = parent - - def __repr__(self): - """Returns a string representation of the context object.""" - stack = [] - context = self - while context: - stack.append(context.type) - context = context.parent - return 'Context(%s)' % ' > '.join(stack) - - -class EcmaMetaData(object): - """Token metadata for EcmaScript languages. - - Attributes: - last_code: The last code token to appear before this one. - context: The context this token appears in. - operator_type: The operator type, will be one of the *_OPERATOR constants - defined below. - """ - - UNARY_OPERATOR = 'unary' - - UNARY_POST_OPERATOR = 'unary_post' - - BINARY_OPERATOR = 'binary' - - TERNARY_OPERATOR = 'ternary' - - def __init__(self): - """Initializes a token metadata object.""" - self.last_code = None - self.context = None - self.operator_type = None - self.is_implied_semicolon = False - self.is_implied_block = False - self.is_implied_block_close = False - - def __repr__(self): - """Returns a string representation of the context object.""" - parts = ['%r' % self.context] - if self.operator_type: - parts.append('optype: %r' % self.operator_type) - if self.is_implied_semicolon: - parts.append('implied;') - return 'MetaData(%s)' % ', '.join(parts) - - def IsUnaryOperator(self): - return self.operator_type in (EcmaMetaData.UNARY_OPERATOR, - EcmaMetaData.UNARY_POST_OPERATOR) - - def IsUnaryPostOperator(self): - return self.operator_type == EcmaMetaData.UNARY_POST_OPERATOR - - -class EcmaMetaDataPass(object): - """A pass that iterates over all tokens and builds metadata about them.""" - - def __init__(self): - """Initialize the meta data pass object.""" - self.Reset() - - def Reset(self): - """Resets the metadata pass to prepare for the next file.""" - self._token = None - self._context = None - self._AddContext(EcmaContext.ROOT) - self._last_code = None - - def _CreateContext(self, type): - """Overridable by subclasses to create the appropriate context type.""" - return EcmaContext(type, self._token, self._context) - - def _CreateMetaData(self): - """Overridable by subclasses to create the appropriate metadata type.""" - return EcmaMetaData() - - def _AddContext(self, type): - """Adds a context of the given type to the context stack. - - Args: - type: The type of context to create - """ - self._context = self._CreateContext(type) - - def _PopContext(self): - """Moves up one level in the context stack. - - Returns: - The former context. - - Raises: - ParseError: If the root context is popped. - """ - top_context = self._context - top_context.end_token = self._token - self._context = top_context.parent - if self._context: - return top_context - else: - raise ParseError(self._token) - - def _PopContextType(self, *stop_types): - """Pops the context stack until a context of the given type is popped. - - Args: - stop_types: The types of context to pop to - stops at the first match. - - Returns: - The context object of the given type that was popped. - """ - last = None - while not last or last.type not in stop_types: - last = self._PopContext() - return last - - def _EndStatement(self): - """Process the end of a statement.""" - self._PopContextType(EcmaContext.STATEMENT) - if self._context.type == EcmaContext.IMPLIED_BLOCK: - self._token.metadata.is_implied_block_close = True - self._PopContext() - - def _ProcessContext(self): - """Process the context at the current token. - - Returns: - The context that should be assigned to the current token, or None if - the current context after this method should be used. - - Raises: - ParseError: When the token appears in an invalid context. - """ - token = self._token - token_type = token.type - - if self._context.type in EcmaContext.BLOCK_TYPES: - # Whenever we're in a block, we add a statement context. We make an - # exception for switch statements since they can only contain case: and - # default: and therefore don't directly contain statements. - # The block we add here may be immediately removed in some cases, but - # that causes no harm. - parent = self._context.parent - if not parent or parent.type != EcmaContext.SWITCH: - self._AddContext(EcmaContext.STATEMENT) - - elif self._context.type == EcmaContext.ARRAY_LITERAL: - self._AddContext(EcmaContext.LITERAL_ELEMENT) - - if token_type == TokenType.START_PAREN: - if self._last_code and self._last_code.IsKeyword('for'): - # for loops contain multiple statements in the group unlike while, - # switch, if, etc. - self._AddContext(EcmaContext.FOR_GROUP_BLOCK) - else: - self._AddContext(EcmaContext.GROUP) - - elif token_type == TokenType.END_PAREN: - result = self._PopContextType(EcmaContext.GROUP, - EcmaContext.FOR_GROUP_BLOCK) - keyword_token = result.start_token.metadata.last_code - # keyword_token will not exist if the open paren is the first line of the - # file, for example if all code is wrapped in an immediately executed - # annonymous function. - if keyword_token and keyword_token.string in ('if', 'for', 'while'): - next_code = tokenutil.SearchExcept(token, TokenType.NON_CODE_TYPES) - if next_code.type != TokenType.START_BLOCK: - # Check for do-while. - is_do_while = False - pre_keyword_token = keyword_token.metadata.last_code - if (pre_keyword_token and - pre_keyword_token.type == TokenType.END_BLOCK): - start_block_token = pre_keyword_token.metadata.context.start_token - is_do_while = start_block_token.metadata.last_code.string == 'do' - - # If it's not do-while, it's an implied block. - if not is_do_while: - self._AddContext(EcmaContext.IMPLIED_BLOCK) - token.metadata.is_implied_block = True - - return result - - # else (not else if) with no open brace after it should be considered the - # start of an implied block, similar to the case with if, for, and while - # above. - elif (token_type == TokenType.KEYWORD and - token.string == 'else'): - next_code = tokenutil.SearchExcept(token, TokenType.NON_CODE_TYPES) - if (next_code.type != TokenType.START_BLOCK and - (next_code.type != TokenType.KEYWORD or next_code.string != 'if')): - self._AddContext(EcmaContext.IMPLIED_BLOCK) - token.metadata.is_implied_block = True - - elif token_type == TokenType.START_PARAMETERS: - self._AddContext(EcmaContext.PARAMETERS) - - elif token_type == TokenType.END_PARAMETERS: - return self._PopContextType(EcmaContext.PARAMETERS) - - elif token_type == TokenType.START_BRACKET: - if (self._last_code and - self._last_code.type in TokenType.EXPRESSION_ENDER_TYPES): - self._AddContext(EcmaContext.INDEX) - else: - self._AddContext(EcmaContext.ARRAY_LITERAL) - - elif token_type == TokenType.END_BRACKET: - return self._PopContextType(EcmaContext.INDEX, EcmaContext.ARRAY_LITERAL) - - elif token_type == TokenType.START_BLOCK: - if (self._last_code.type in (TokenType.END_PAREN, - TokenType.END_PARAMETERS) or - self._last_code.IsKeyword('else') or - self._last_code.IsKeyword('do') or - self._last_code.IsKeyword('try') or - self._last_code.IsKeyword('finally') or - (self._last_code.IsOperator(':') and - self._last_code.metadata.context.type == EcmaContext.CASE_BLOCK)): - # else, do, try, and finally all might have no () before {. - # Also, handle the bizzare syntax case 10: {...}. - self._AddContext(EcmaContext.BLOCK) - else: - self._AddContext(EcmaContext.OBJECT_LITERAL) - - elif token_type == TokenType.END_BLOCK: - context = self._PopContextType(EcmaContext.BLOCK, - EcmaContext.OBJECT_LITERAL) - if self._context.type == EcmaContext.SWITCH: - # The end of the block also means the end of the switch statement it - # applies to. - return self._PopContext() - return context - - elif token.IsKeyword('switch'): - self._AddContext(EcmaContext.SWITCH) - - elif (token_type == TokenType.KEYWORD and - token.string in ('case', 'default')): - # Pop up to but not including the switch block. - while self._context.parent.type != EcmaContext.SWITCH: - self._PopContext() - - elif token.IsOperator('?'): - self._AddContext(EcmaContext.TERNARY_TRUE) - - elif token.IsOperator(':'): - if self._context.type == EcmaContext.OBJECT_LITERAL: - self._AddContext(EcmaContext.LITERAL_ELEMENT) - - elif self._context.type == EcmaContext.TERNARY_TRUE: - self._PopContext() - self._AddContext(EcmaContext.TERNARY_FALSE) - - # Handle nested ternary statements like: - # foo = bar ? baz ? 1 : 2 : 3 - # When we encounter the second ":" the context is - # ternary_false > ternary_true > statement > root - elif (self._context.type == EcmaContext.TERNARY_FALSE and - self._context.parent.type == EcmaContext.TERNARY_TRUE): - self._PopContext() # Leave current ternary false context. - self._PopContext() # Leave current parent ternary true - self._AddContext(EcmaContext.TERNARY_FALSE) - - elif self._context.parent.type == EcmaContext.SWITCH: - self._AddContext(EcmaContext.CASE_BLOCK) - - elif token.IsKeyword('var'): - self._AddContext(EcmaContext.VAR) - - elif token.IsOperator(','): - while self._context.type not in (EcmaContext.VAR, - EcmaContext.ARRAY_LITERAL, - EcmaContext.OBJECT_LITERAL, - EcmaContext.STATEMENT, - EcmaContext.PARAMETERS, - EcmaContext.GROUP): - self._PopContext() - - elif token_type == TokenType.SEMICOLON: - self._EndStatement() - - def Process(self, first_token): - """Processes the token stream starting with the given token.""" - self._token = first_token - while self._token: - self._ProcessToken() - - if self._token.IsCode(): - self._last_code = self._token - - self._token = self._token.next - - try: - self._PopContextType(self, EcmaContext.ROOT) - except ParseError: - # Ignore the "popped to root" error. - pass - - def _ProcessToken(self): - """Process the given token.""" - token = self._token - token.metadata = self._CreateMetaData() - context = (self._ProcessContext() or self._context) - token.metadata.context = context - token.metadata.last_code = self._last_code - - # Determine the operator type of the token, if applicable. - if token.type == TokenType.OPERATOR: - token.metadata.operator_type = self._GetOperatorType(token) - - # Determine if there is an implied semicolon after the token. - if token.type != TokenType.SEMICOLON: - next_code = tokenutil.SearchExcept(token, TokenType.NON_CODE_TYPES) - # A statement like if (x) does not need a semicolon after it - is_implied_block = self._context == EcmaContext.IMPLIED_BLOCK - is_last_code_in_line = token.IsCode() and ( - not next_code or next_code.line_number != token.line_number) - is_continued_identifier = (token.type == TokenType.IDENTIFIER and - token.string.endswith('.')) - is_continued_operator = (token.type == TokenType.OPERATOR and - not token.metadata.IsUnaryPostOperator()) - is_continued_dot = token.string == '.' - next_code_is_operator = next_code and next_code.type == TokenType.OPERATOR - next_code_is_dot = next_code and next_code.string == '.' - is_end_of_block = (token.type == TokenType.END_BLOCK and - token.metadata.context.type != EcmaContext.OBJECT_LITERAL) - is_multiline_string = token.type == TokenType.STRING_TEXT - next_code_is_block = next_code and next_code.type == TokenType.START_BLOCK - if (is_last_code_in_line and - self._StatementCouldEndInContext() and - not is_multiline_string and - not is_end_of_block and - not is_continued_identifier and - not is_continued_operator and - not is_continued_dot and - not next_code_is_dot and - not next_code_is_operator and - not is_implied_block and - not next_code_is_block): - token.metadata.is_implied_semicolon = True - self._EndStatement() - - def _StatementCouldEndInContext(self): - """Returns whether the current statement (if any) may end in this context.""" - # In the basic statement or variable declaration context, statement can - # always end in this context. - if self._context.type in (EcmaContext.STATEMENT, EcmaContext.VAR): - return True - - # End of a ternary false branch inside a statement can also be the - # end of the statement, for example: - # var x = foo ? foo.bar() : null - # In this case the statement ends after the null, when the context stack - # looks like ternary_false > var > statement > root. - if (self._context.type == EcmaContext.TERNARY_FALSE and - self._context.parent.type in (EcmaContext.STATEMENT, EcmaContext.VAR)): - return True - - # In all other contexts like object and array literals, ternary true, etc. - # the statement can't yet end. - return False - - def _GetOperatorType(self, token): - """Returns the operator type of the given operator token. - - Args: - token: The token to get arity for. - - Returns: - The type of the operator. One of the *_OPERATOR constants defined in - EcmaMetaData. - """ - if token.string == '?': - return EcmaMetaData.TERNARY_OPERATOR - - if token.string in TokenType.UNARY_OPERATORS: - return EcmaMetaData.UNARY_OPERATOR - - last_code = token.metadata.last_code - if not last_code or last_code.type == TokenType.END_BLOCK: - return EcmaMetaData.UNARY_OPERATOR - - if (token.string in TokenType.UNARY_POST_OPERATORS and - last_code.type in TokenType.EXPRESSION_ENDER_TYPES): - return EcmaMetaData.UNARY_POST_OPERATOR - - if (token.string in TokenType.UNARY_OK_OPERATORS and - last_code.type not in TokenType.EXPRESSION_ENDER_TYPES and - last_code.string not in TokenType.UNARY_POST_OPERATORS): - return EcmaMetaData.UNARY_OPERATOR - - return EcmaMetaData.BINARY_OPERATOR diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/error_check.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/error_check.py deleted file mode 100755 index ed243e91..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/error_check.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2011 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - - -"""Specific JSLint errors checker.""" - - - -import gflags as flags - -FLAGS = flags.FLAGS - - -class Rule(object): - """Different rules to check.""" - - # Documentations for specific rules goes in flag definition. - BLANK_LINES_AT_TOP_LEVEL = 'blank_lines_at_top_level' - INDENTATION = 'indentation' - WELL_FORMED_AUTHOR = 'well_formed_author' - NO_BRACES_AROUND_INHERIT_DOC = 'no_braces_around_inherit_doc' - BRACES_AROUND_TYPE = 'braces_around_type' - OPTIONAL_TYPE_MARKER = 'optional_type_marker' - UNUSED_PRIVATE_MEMBERS = 'unused_private_members' - - # Rule to raise all known errors. - ALL = 'all' - - # All rules that are to be checked when using the strict flag. E.g. the rules - # that are specific to the stricter Closure style. - CLOSURE_RULES = frozenset([BLANK_LINES_AT_TOP_LEVEL, - INDENTATION, - WELL_FORMED_AUTHOR, - NO_BRACES_AROUND_INHERIT_DOC, - BRACES_AROUND_TYPE, - OPTIONAL_TYPE_MARKER]) - - -flags.DEFINE_boolean('strict', False, - 'Whether to validate against the stricter Closure style. ' - 'This includes ' + (', '.join(Rule.CLOSURE_RULES)) + '.') -flags.DEFINE_multistring('jslint_error', [], - 'List of specific lint errors to check. Here is a list' - ' of accepted values:\n' - ' - ' + Rule.ALL + ': enables all following errors.\n' - ' - ' + Rule.BLANK_LINES_AT_TOP_LEVEL + ': validates' - 'number of blank lines between blocks at top level.\n' - ' - ' + Rule.INDENTATION + ': checks correct ' - 'indentation of code.\n' - ' - ' + Rule.WELL_FORMED_AUTHOR + ': validates the ' - '@author JsDoc tags.\n' - ' - ' + Rule.NO_BRACES_AROUND_INHERIT_DOC + ': ' - 'forbids braces around @inheritdoc JsDoc tags.\n' - ' - ' + Rule.BRACES_AROUND_TYPE + ': enforces braces ' - 'around types in JsDoc tags.\n' - ' - ' + Rule.OPTIONAL_TYPE_MARKER + ': checks correct ' - 'use of optional marker = in param types.\n' - ' - ' + Rule.UNUSED_PRIVATE_MEMBERS + ': checks for ' - 'unused private variables.\n') - - -def ShouldCheck(rule): - """Returns whether the optional rule should be checked. - - Computes different flags (strict, jslint_error, jslint_noerror) to find out if - this specific rule should be checked. - - Args: - rule: Name of the rule (see Rule). - - Returns: - True if the rule should be checked according to the flags, otherwise False. - """ - if rule in FLAGS.jslint_error or Rule.ALL in FLAGS.jslint_error: - return True - # Checks strict rules. - return FLAGS.strict and rule in Rule.CLOSURE_RULES diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/error_fixer.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/error_fixer.py deleted file mode 100755 index 92e22212..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/error_fixer.py +++ /dev/null @@ -1,447 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Main class responsible for automatically fixing simple style violations.""" - -__author__ = 'robbyw@google.com (Robert Walker)' - -import re - -import gflags as flags -from closure_linter import errors -from closure_linter import javascriptstatetracker -from closure_linter import javascripttokens -from closure_linter import requireprovidesorter -from closure_linter import tokenutil -from closure_linter.common import errorhandler - -# Shorthand -Token = javascripttokens.JavaScriptToken -Type = javascripttokens.JavaScriptTokenType - -END_OF_FLAG_TYPE = re.compile(r'(}?\s*)$') - -# Regex to represent common mistake inverting author name and email as -# @author User Name (user@company) -INVERTED_AUTHOR_SPEC = re.compile(r'(?P\s*)' - '(?P[^(]+)' - '(?P\s+)' - '\(' - '(?P[^\s]+@[^)\s]+)' - '\)' - '(?P.*)') - -FLAGS = flags.FLAGS -flags.DEFINE_boolean('disable_indentation_fixing', False, - 'Whether to disable automatic fixing of indentation.') - - -class ErrorFixer(errorhandler.ErrorHandler): - """Object that fixes simple style errors.""" - - def __init__(self, external_file=None): - """Initialize the error fixer. - - Args: - external_file: If included, all output will be directed to this file - instead of overwriting the files the errors are found in. - """ - errorhandler.ErrorHandler.__init__(self) - - self._file_name = None - self._file_token = None - self._external_file = external_file - - def HandleFile(self, filename, first_token): - """Notifies this ErrorPrinter that subsequent errors are in filename. - - Args: - filename: The name of the file about to be checked. - first_token: The first token in the file. - """ - self._file_name = filename - self._file_token = first_token - self._file_fix_count = 0 - self._file_changed_lines = set() - - def _AddFix(self, tokens): - """Adds the fix to the internal count. - - Args: - tokens: The token or sequence of tokens changed to fix an error. - """ - self._file_fix_count += 1 - if hasattr(tokens, 'line_number'): - self._file_changed_lines.add(tokens.line_number) - else: - for token in tokens: - self._file_changed_lines.add(token.line_number) - - def HandleError(self, error): - """Attempts to fix the error. - - Args: - error: The error object - """ - code = error.code - token = error.token - - if code == errors.JSDOC_PREFER_QUESTION_TO_PIPE_NULL: - iterator = token.attached_object.type_start_token - if iterator.type == Type.DOC_START_BRACE or iterator.string.isspace(): - iterator = iterator.next - - leading_space = len(iterator.string) - len(iterator.string.lstrip()) - iterator.string = '%s?%s' % (' ' * leading_space, - iterator.string.lstrip()) - - # Cover the no outer brace case where the end token is part of the type. - while iterator and iterator != token.attached_object.type_end_token.next: - iterator.string = iterator.string.replace( - 'null|', '').replace('|null', '') - iterator = iterator.next - - # Create a new flag object with updated type info. - token.attached_object = javascriptstatetracker.JsDocFlag(token) - self._AddFix(token) - - elif code == errors.JSDOC_MISSING_OPTIONAL_TYPE: - iterator = token.attached_object.type_end_token - if iterator.type == Type.DOC_END_BRACE or iterator.string.isspace(): - iterator = iterator.previous - - ending_space = len(iterator.string) - len(iterator.string.rstrip()) - iterator.string = '%s=%s' % (iterator.string.rstrip(), - ' ' * ending_space) - - # Create a new flag object with updated type info. - token.attached_object = javascriptstatetracker.JsDocFlag(token) - self._AddFix(token) - - elif code in (errors.MISSING_SEMICOLON_AFTER_FUNCTION, - errors.MISSING_SEMICOLON): - semicolon_token = Token(';', Type.SEMICOLON, token.line, - token.line_number) - tokenutil.InsertTokenAfter(semicolon_token, token) - token.metadata.is_implied_semicolon = False - semicolon_token.metadata.is_implied_semicolon = False - self._AddFix(token) - - elif code in (errors.ILLEGAL_SEMICOLON_AFTER_FUNCTION, - errors.REDUNDANT_SEMICOLON, - errors.COMMA_AT_END_OF_LITERAL): - tokenutil.DeleteToken(token) - self._AddFix(token) - - elif code == errors.INVALID_JSDOC_TAG: - if token.string == '@returns': - token.string = '@return' - self._AddFix(token) - - elif code == errors.FILE_MISSING_NEWLINE: - # This error is fixed implicitly by the way we restore the file - self._AddFix(token) - - elif code == errors.MISSING_SPACE: - if error.position: - if error.position.IsAtBeginning(): - tokenutil.InsertSpaceTokenAfter(token.previous) - elif error.position.IsAtEnd(token.string): - tokenutil.InsertSpaceTokenAfter(token) - else: - token.string = error.position.Set(token.string, ' ') - self._AddFix(token) - - elif code == errors.EXTRA_SPACE: - if error.position: - token.string = error.position.Set(token.string, '') - self._AddFix(token) - - elif code == errors.JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER: - token.string = error.position.Set(token.string, '.') - self._AddFix(token) - - elif code == errors.MISSING_LINE: - if error.position.IsAtBeginning(): - tokenutil.InsertBlankLineAfter(token.previous) - else: - tokenutil.InsertBlankLineAfter(token) - self._AddFix(token) - - elif code == errors.EXTRA_LINE: - tokenutil.DeleteToken(token) - self._AddFix(token) - - elif code == errors.WRONG_BLANK_LINE_COUNT: - if not token.previous: - # TODO(user): Add an insertBefore method to tokenutil. - return - - num_lines = error.fix_data - should_delete = False - - if num_lines < 0: - num_lines *= -1 - should_delete = True - - for i in xrange(1, num_lines + 1): - if should_delete: - # TODO(user): DeleteToken should update line numbers. - tokenutil.DeleteToken(token.previous) - else: - tokenutil.InsertBlankLineAfter(token.previous) - self._AddFix(token) - - elif code == errors.UNNECESSARY_DOUBLE_QUOTED_STRING: - end_quote = tokenutil.Search(token, Type.DOUBLE_QUOTE_STRING_END) - if end_quote: - single_quote_start = Token( - "'", Type.SINGLE_QUOTE_STRING_START, token.line, token.line_number) - single_quote_end = Token( - "'", Type.SINGLE_QUOTE_STRING_START, end_quote.line, - token.line_number) - - tokenutil.InsertTokenAfter(single_quote_start, token) - tokenutil.InsertTokenAfter(single_quote_end, end_quote) - tokenutil.DeleteToken(token) - tokenutil.DeleteToken(end_quote) - self._AddFix([token, end_quote]) - - elif code == errors.MISSING_BRACES_AROUND_TYPE: - fixed_tokens = [] - start_token = token.attached_object.type_start_token - - if start_token.type != Type.DOC_START_BRACE: - leading_space = ( - len(start_token.string) - len(start_token.string.lstrip())) - if leading_space: - start_token = tokenutil.SplitToken(start_token, leading_space) - # Fix case where start and end token were the same. - if token.attached_object.type_end_token == start_token.previous: - token.attached_object.type_end_token = start_token - - new_token = Token('{', Type.DOC_START_BRACE, start_token.line, - start_token.line_number) - tokenutil.InsertTokenAfter(new_token, start_token.previous) - token.attached_object.type_start_token = new_token - fixed_tokens.append(new_token) - - end_token = token.attached_object.type_end_token - if end_token.type != Type.DOC_END_BRACE: - # If the start token was a brace, the end token will be a - # FLAG_ENDING_TYPE token, if there wasn't a starting brace then - # the end token is the last token of the actual type. - last_type = end_token - if not fixed_tokens: - last_type = end_token.previous - - while last_type.string.isspace(): - last_type = last_type.previous - - # If there was no starting brace then a lone end brace wouldn't have - # been type end token. Now that we've added any missing start brace, - # see if the last effective type token was an end brace. - if last_type.type != Type.DOC_END_BRACE: - trailing_space = (len(last_type.string) - - len(last_type.string.rstrip())) - if trailing_space: - tokenutil.SplitToken(last_type, - len(last_type.string) - trailing_space) - - new_token = Token('}', Type.DOC_END_BRACE, last_type.line, - last_type.line_number) - tokenutil.InsertTokenAfter(new_token, last_type) - token.attached_object.type_end_token = new_token - fixed_tokens.append(new_token) - - self._AddFix(fixed_tokens) - - elif code == errors.GOOG_REQUIRES_NOT_ALPHABETIZED: - require_start_token = error.fix_data - sorter = requireprovidesorter.RequireProvideSorter() - sorter.FixRequires(require_start_token) - - self._AddFix(require_start_token) - - elif code == errors.GOOG_PROVIDES_NOT_ALPHABETIZED: - provide_start_token = error.fix_data - sorter = requireprovidesorter.RequireProvideSorter() - sorter.FixProvides(provide_start_token) - - self._AddFix(provide_start_token) - - elif code == errors.UNNECESSARY_BRACES_AROUND_INHERIT_DOC: - if token.previous.string == '{' and token.next.string == '}': - tokenutil.DeleteToken(token.previous) - tokenutil.DeleteToken(token.next) - self._AddFix([token]) - - elif code == errors.INVALID_AUTHOR_TAG_DESCRIPTION: - match = INVERTED_AUTHOR_SPEC.match(token.string) - if match: - token.string = '%s%s%s(%s)%s' % (match.group('leading_whitespace'), - match.group('email'), - match.group('whitespace_after_name'), - match.group('name'), - match.group('trailing_characters')) - self._AddFix(token) - - elif (code == errors.WRONG_INDENTATION and - not FLAGS.disable_indentation_fixing): - token = tokenutil.GetFirstTokenInSameLine(token) - actual = error.position.start - expected = error.position.length - - if token.type in (Type.WHITESPACE, Type.PARAMETERS) and actual != 0: - token.string = token.string.lstrip() + (' ' * expected) - self._AddFix([token]) - else: - # We need to add indentation. - new_token = Token(' ' * expected, Type.WHITESPACE, - token.line, token.line_number) - # Note that we'll never need to add indentation at the first line, - # since it will always not be indented. Therefore it's safe to assume - # token.previous exists. - tokenutil.InsertTokenAfter(new_token, token.previous) - self._AddFix([token]) - - elif code in [errors.MALFORMED_END_OF_SCOPE_COMMENT, - errors.MISSING_END_OF_SCOPE_COMMENT]: - # Only fix cases where }); is found with no trailing content on the line - # other than a comment. Value of 'token' is set to } for this error. - if (token.type == Type.END_BLOCK and - token.next.type == Type.END_PAREN and - token.next.next.type == Type.SEMICOLON): - current_token = token.next.next.next - removed_tokens = [] - while current_token and current_token.line_number == token.line_number: - if current_token.IsAnyType(Type.WHITESPACE, - Type.START_SINGLE_LINE_COMMENT, - Type.COMMENT): - removed_tokens.append(current_token) - current_token = current_token.next - else: - return - - if removed_tokens: - tokenutil.DeleteTokens(removed_tokens[0], len(removed_tokens)) - - whitespace_token = Token(' ', Type.WHITESPACE, token.line, - token.line_number) - start_comment_token = Token('//', Type.START_SINGLE_LINE_COMMENT, - token.line, token.line_number) - comment_token = Token(' goog.scope', Type.COMMENT, token.line, - token.line_number) - insertion_tokens = [whitespace_token, start_comment_token, - comment_token] - - tokenutil.InsertTokensAfter(insertion_tokens, token.next.next) - self._AddFix(removed_tokens + insertion_tokens) - - elif code in [errors.EXTRA_GOOG_PROVIDE, errors.EXTRA_GOOG_REQUIRE]: - tokens_in_line = tokenutil.GetAllTokensInSameLine(token) - tokenutil.DeleteTokens(tokens_in_line[0], len(tokens_in_line)) - self._AddFix(tokens_in_line) - - elif code in [errors.MISSING_GOOG_PROVIDE, errors.MISSING_GOOG_REQUIRE]: - is_provide = code == errors.MISSING_GOOG_PROVIDE - is_require = code == errors.MISSING_GOOG_REQUIRE - - missing_namespaces = error.fix_data[0] - need_blank_line = error.fix_data[1] - - if need_blank_line is None: - # TODO(user): This happens when there are no existing - # goog.provide or goog.require statements to position new statements - # relative to. Consider handling this case with a heuristic. - return - - insert_location = token.previous - - # If inserting a missing require with no existing requires, insert a - # blank line first. - if need_blank_line and is_require: - tokenutil.InsertBlankLineAfter(insert_location) - insert_location = insert_location.next - - for missing_namespace in missing_namespaces: - new_tokens = self._GetNewRequireOrProvideTokens( - is_provide, missing_namespace, insert_location.line_number + 1) - tokenutil.InsertLineAfter(insert_location, new_tokens) - insert_location = new_tokens[-1] - self._AddFix(new_tokens) - - # If inserting a missing provide with no existing provides, insert a - # blank line after. - if need_blank_line and is_provide: - tokenutil.InsertBlankLineAfter(insert_location) - - def _GetNewRequireOrProvideTokens(self, is_provide, namespace, line_number): - """Returns a list of tokens to create a goog.require/provide statement. - - Args: - is_provide: True if getting tokens for a provide, False for require. - namespace: The required or provided namespaces to get tokens for. - line_number: The line number the new require or provide statement will be - on. - - Returns: - Tokens to create a new goog.require or goog.provide statement. - """ - string = 'goog.require' - if is_provide: - string = 'goog.provide' - line_text = string + '(\'' + namespace + '\');\n' - return [ - Token(string, Type.IDENTIFIER, line_text, line_number), - Token('(', Type.START_PAREN, line_text, line_number), - Token('\'', Type.SINGLE_QUOTE_STRING_START, line_text, line_number), - Token(namespace, Type.STRING_TEXT, line_text, line_number), - Token('\'', Type.SINGLE_QUOTE_STRING_END, line_text, line_number), - Token(')', Type.END_PAREN, line_text, line_number), - Token(';', Type.SEMICOLON, line_text, line_number) - ] - - def FinishFile(self): - """Called when the current file has finished style checking. - - Used to go back and fix any errors in the file. - """ - if self._file_fix_count: - f = self._external_file - if not f: - print 'Fixed %d errors in %s' % (self._file_fix_count, self._file_name) - f = open(self._file_name, 'w') - - token = self._file_token - char_count = 0 - while token: - f.write(token.string) - char_count += len(token.string) - - if token.IsLastInLine(): - f.write('\n') - if char_count > 80 and token.line_number in self._file_changed_lines: - print 'WARNING: Line %d of %s is now longer than 80 characters.' % ( - token.line_number, self._file_name) - - char_count = 0 - - token = token.next - - if not self._external_file: - # Close the file if we created it - f.close() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errorrecord.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errorrecord.py deleted file mode 100755 index 6b253eb0..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errorrecord.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# Copyright 2012 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - - -"""A simple, pickle-serializable class to represent a lint error.""" - - - -import gflags as flags - -from closure_linter import errors -from closure_linter.common import erroroutput - -FLAGS = flags.FLAGS - - -class ErrorRecord(object): - """Record-keeping struct that can be serialized back from a process. - - Attributes: - path: Path to the file. - error_string: Error string for the user. - new_error: Whether this is a "new error" (see errors.NEW_ERRORS). - """ - - def __init__(self, path, error_string, new_error): - self.path = path - self.error_string = error_string - self.new_error = new_error - - -def MakeErrorRecord(path, error): - """Make an error record with correctly formatted error string. - - Errors are not able to be serialized (pickled) over processes because of - their pointers to the complex token/context graph. We use an intermediary - serializable class to pass back just the relevant information. - - Args: - path: Path of file the error was found in. - error: An error.Error instance. - - Returns: - _ErrorRecord instance. - """ - new_error = error.code in errors.NEW_ERRORS - - if FLAGS.unix_mode: - error_string = erroroutput.GetUnixErrorOutput(path, error, new_error) - else: - error_string = erroroutput.GetErrorOutput(error, new_error) - - return ErrorRecord(path, error_string, new_error) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errorrules.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errorrules.py deleted file mode 100755 index afb6fa96..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errorrules.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Linter error rules class for Closure Linter.""" - -__author__ = 'robbyw@google.com (Robert Walker)' - -import gflags as flags -from closure_linter import errors - - -FLAGS = flags.FLAGS -flags.DEFINE_boolean('jsdoc', True, - 'Whether to report errors for missing JsDoc.') - - -def ShouldReportError(error): - """Whether the given error should be reported. - - Returns: - True for all errors except missing documentation errors. For these, - it returns the value of the jsdoc flag. - """ - return FLAGS.jsdoc or error not in ( - errors.MISSING_PARAMETER_DOCUMENTATION, - errors.MISSING_RETURN_DOCUMENTATION, - errors.MISSING_MEMBER_DOCUMENTATION, - errors.MISSING_PRIVATE, - errors.MISSING_JSDOC_TAG_THIS) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errors.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errors.py deleted file mode 100755 index 08c6dbe0..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/errors.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Error codes for JavaScript style checker.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - - -def ByName(name): - """Get the error code for the given error name. - - Args: - name: The name of the error - - Returns: - The error code - """ - return globals()[name] - - -# "File-fatal" errors - these errors stop further parsing of a single file -FILE_NOT_FOUND = -1 -FILE_DOES_NOT_PARSE = -2 - -# Spacing -EXTRA_SPACE = 1 -MISSING_SPACE = 2 -EXTRA_LINE = 3 -MISSING_LINE = 4 -ILLEGAL_TAB = 5 -WRONG_INDENTATION = 6 -WRONG_BLANK_LINE_COUNT = 7 - -# Semicolons -MISSING_SEMICOLON = 10 -MISSING_SEMICOLON_AFTER_FUNCTION = 11 -ILLEGAL_SEMICOLON_AFTER_FUNCTION = 12 -REDUNDANT_SEMICOLON = 13 - -# Miscellaneous -ILLEGAL_PROTOTYPE_MEMBER_VALUE = 100 -LINE_TOO_LONG = 110 -LINE_STARTS_WITH_OPERATOR = 120 -COMMA_AT_END_OF_LITERAL = 121 -MULTI_LINE_STRING = 130 -UNNECESSARY_DOUBLE_QUOTED_STRING = 131 -UNUSED_PRIVATE_MEMBER = 132 - -# Requires, provides -GOOG_REQUIRES_NOT_ALPHABETIZED = 140 -GOOG_PROVIDES_NOT_ALPHABETIZED = 141 -MISSING_GOOG_REQUIRE = 142 -MISSING_GOOG_PROVIDE = 143 -EXTRA_GOOG_REQUIRE = 144 -EXTRA_GOOG_PROVIDE = 145 - -# JsDoc -INVALID_JSDOC_TAG = 200 -INVALID_USE_OF_DESC_TAG = 201 -NO_BUG_NUMBER_AFTER_BUG_TAG = 202 -MISSING_PARAMETER_DOCUMENTATION = 210 -EXTRA_PARAMETER_DOCUMENTATION = 211 -WRONG_PARAMETER_DOCUMENTATION = 212 -MISSING_JSDOC_TAG_TYPE = 213 -MISSING_JSDOC_TAG_DESCRIPTION = 214 -MISSING_JSDOC_PARAM_NAME = 215 -OUT_OF_ORDER_JSDOC_TAG_TYPE = 216 -MISSING_RETURN_DOCUMENTATION = 217 -UNNECESSARY_RETURN_DOCUMENTATION = 218 -MISSING_BRACES_AROUND_TYPE = 219 -MISSING_MEMBER_DOCUMENTATION = 220 -MISSING_PRIVATE = 221 -EXTRA_PRIVATE = 222 -INVALID_OVERRIDE_PRIVATE = 223 -INVALID_INHERIT_DOC_PRIVATE = 224 -MISSING_JSDOC_TAG_THIS = 225 -UNNECESSARY_BRACES_AROUND_INHERIT_DOC = 226 -INVALID_AUTHOR_TAG_DESCRIPTION = 227 -JSDOC_PREFER_QUESTION_TO_PIPE_NULL = 230 -JSDOC_ILLEGAL_QUESTION_WITH_PIPE = 231 -JSDOC_MISSING_OPTIONAL_TYPE = 232 -JSDOC_MISSING_OPTIONAL_PREFIX = 233 -JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER = 240 -# TODO(robbyw): Split this in to more specific syntax problems. -INCORRECT_SUPPRESS_SYNTAX = 250 -INVALID_SUPPRESS_TYPE = 251 -UNNECESSARY_SUPPRESS = 252 - -# File ending -FILE_MISSING_NEWLINE = 300 -FILE_IN_BLOCK = 301 - -# Interfaces -INTERFACE_CONSTRUCTOR_CANNOT_HAVE_PARAMS = 400 -INTERFACE_METHOD_CANNOT_HAVE_CODE = 401 - -# Comments -MISSING_END_OF_SCOPE_COMMENT = 500 -MALFORMED_END_OF_SCOPE_COMMENT = 501 - -# ActionScript specific errors: -# TODO(user): move these errors to their own file and move all JavaScript -# specific errors to their own file as well. -# All ActionScript specific errors should have error number at least 1000. -FUNCTION_MISSING_RETURN_TYPE = 1132 -PARAMETER_MISSING_TYPE = 1133 -VAR_MISSING_TYPE = 1134 -PARAMETER_MISSING_DEFAULT_VALUE = 1135 -IMPORTS_NOT_ALPHABETIZED = 1140 -IMPORT_CONTAINS_WILDCARD = 1141 -UNUSED_IMPORT = 1142 -INVALID_TRACE_SEVERITY_LEVEL = 1250 -MISSING_TRACE_SEVERITY_LEVEL = 1251 -MISSING_TRACE_MESSAGE = 1252 -REMOVE_TRACE_BEFORE_SUBMIT = 1253 -REMOVE_COMMENT_BEFORE_SUBMIT = 1254 -# End of list of ActionScript specific errors. - -NEW_ERRORS = frozenset([ - # Errors added after 2.0.2: - WRONG_INDENTATION, - MISSING_SEMICOLON, - # Errors added after 2.3.4: - MISSING_END_OF_SCOPE_COMMENT, - MALFORMED_END_OF_SCOPE_COMMENT, - UNUSED_PRIVATE_MEMBER, - # Errors added after 2.3.5: - ]) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/fixjsstyle.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/fixjsstyle.py deleted file mode 100755 index c23f6b75..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/fixjsstyle.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python -# python2.6 for command-line runs using p4lib. pylint: disable-msg=C6301 -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Automatically fix simple style guide violations.""" - -__author__ = 'robbyw@google.com (Robert Walker)' - -import sys - -import gflags as flags -from closure_linter import checker -from closure_linter import error_fixer -from closure_linter.common import simplefileflags as fileflags - -FLAGS = flags.FLAGS -flags.DEFINE_list('additional_extensions', None, 'List of additional file ' - 'extensions (not js) that should be treated as ' - 'JavaScript files.') - - -def main(argv = None): - """Main function. - - Args: - argv: Sequence of command line arguments. - """ - if argv is None: - argv = flags.FLAGS(sys.argv) - - suffixes = ['.js'] - if FLAGS.additional_extensions: - suffixes += ['.%s' % ext for ext in FLAGS.additional_extensions] - - files = fileflags.GetFileList(argv, 'JavaScript', suffixes) - - style_checker = checker.JavaScriptStyleChecker(error_fixer.ErrorFixer()) - - # Check the list of files. - for filename in files: - style_checker.Check(filename) - -if __name__ == '__main__': - main() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/fixjsstyle_test.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/fixjsstyle_test.py deleted file mode 100755 index 5096568d..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/fixjsstyle_test.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Medium tests for the gpylint auto-fixer.""" - -__author__ = 'robbyw@google.com (Robby Walker)' - -import StringIO - -import gflags as flags -import unittest as googletest -from closure_linter import checker -from closure_linter import error_fixer - -_RESOURCE_PREFIX = 'closure_linter/testdata' - -flags.FLAGS.strict = True -flags.FLAGS.limited_doc_files = ('dummy.js', 'externs.js') -flags.FLAGS.closurized_namespaces = ('goog', 'dummy') - - -class FixJsStyleTest(googletest.TestCase): - """Test case to for gjslint auto-fixing.""" - - def testFixJsStyle(self): - test_cases = [['fixjsstyle.in.js', 'fixjsstyle.out.js'], - ['indentation.js', 'fixjsstyle.indentation.out.js']] - for [running_input_file, running_output_file] in test_cases: - input_filename = None - golden_filename = None - current_filename = None - try: - input_filename = '%s/%s' % (_RESOURCE_PREFIX, running_input_file) - current_filename = input_filename - - golden_filename = '%s/%s' % (_RESOURCE_PREFIX, running_output_file) - current_filename = golden_filename - except IOError, ex: - raise IOError('Could not find testdata resource for %s: %s' % - (current_filename, ex)) - - if running_input_file == 'fixjsstyle.in.js': - with open(input_filename) as f: - for line in f: - # Go to last line. - pass - self.assertTrue(line == line.rstrip(), '%s file should not end ' - 'with a new line.' % (input_filename)) - - # Autofix the file, sending output to a fake file. - actual = StringIO.StringIO() - style_checker = checker.JavaScriptStyleChecker( - error_fixer.ErrorFixer(actual)) - style_checker.Check(input_filename) - - # Now compare the files. - actual.seek(0) - expected = open(golden_filename, 'r') - - self.assertEqual(actual.readlines(), expected.readlines()) - - def testMissingExtraAndUnsortedRequires(self): - """Tests handling of missing extra and unsorted goog.require statements.""" - original = [ - "goog.require('dummy.aa');", - "goog.require('dummy.Cc');", - "goog.require('dummy.Dd');", - "", - "var x = new dummy.Bb();", - "dummy.Cc.someMethod();", - "dummy.aa.someMethod();", - ] - - expected = [ - "goog.require('dummy.Bb');", - "goog.require('dummy.Cc');", - "goog.require('dummy.aa');", - "", - "var x = new dummy.Bb();", - "dummy.Cc.someMethod();", - "dummy.aa.someMethod();", - ] - - self._AssertFixes(original, expected) - - def testMissingExtraAndUnsortedProvides(self): - """Tests handling of missing extra and unsorted goog.provide statements.""" - original = [ - "goog.provide('dummy.aa');", - "goog.provide('dummy.Cc');", - "goog.provide('dummy.Dd');", - "", - "dummy.Cc = function() {};", - "dummy.Bb = function() {};", - "dummy.aa.someMethod = function();", - ] - - expected = [ - "goog.provide('dummy.Bb');", - "goog.provide('dummy.Cc');", - "goog.provide('dummy.aa');", - "", - "dummy.Cc = function() {};", - "dummy.Bb = function() {};", - "dummy.aa.someMethod = function();", - ] - - self._AssertFixes(original, expected) - - def testNoRequires(self): - """Tests positioning of missing requires without existing requires.""" - original = [ - "goog.provide('dummy.Something');", - "", - "dummy.Something = function() {};", - "", - "var x = new dummy.Bb();", - ] - - expected = [ - "goog.provide('dummy.Something');", - "", - "goog.require('dummy.Bb');", - "", - "dummy.Something = function() {};", - "", - "var x = new dummy.Bb();", - ] - - self._AssertFixes(original, expected) - - def testNoProvides(self): - """Tests positioning of missing provides without existing provides.""" - original = [ - "goog.require('dummy.Bb');", - "", - "dummy.Something = function() {};", - "", - "var x = new dummy.Bb();", - ] - - expected = [ - "goog.provide('dummy.Something');", - "", - "goog.require('dummy.Bb');", - "", - "dummy.Something = function() {};", - "", - "var x = new dummy.Bb();", - ] - - self._AssertFixes(original, expected) - - def testGoogScopeIndentation(self): - """Tests Handling a typical end-of-scope indentation fix.""" - original = [ - 'goog.scope(function() {', - ' // TODO(brain): Take over the world.', - '}); // goog.scope', - ] - - expected = [ - 'goog.scope(function() {', - '// TODO(brain): Take over the world.', - '}); // goog.scope', - ] - - self._AssertFixes(original, expected) - - def testMissingEndOfScopeComment(self): - """Tests Handling a missing comment at end of goog.scope.""" - original = [ - 'goog.scope(function() {', - '});', - ] - - expected = [ - 'goog.scope(function() {', - '}); // goog.scope', - ] - - self._AssertFixes(original, expected) - - def testMissingEndOfScopeCommentWithOtherComment(self): - """Tests handling an irrelevant comment at end of goog.scope.""" - original = [ - 'goog.scope(function() {', - "}); // I don't belong here!", - ] - - expected = [ - 'goog.scope(function() {', - '}); // goog.scope', - ] - - self._AssertFixes(original, expected) - - def testMalformedEndOfScopeComment(self): - """Tests Handling a malformed comment at end of goog.scope.""" - original = [ - 'goog.scope(function() {', - '}); // goog.scope FTW', - ] - - expected = [ - 'goog.scope(function() {', - '}); // goog.scope', - ] - - self._AssertFixes(original, expected) - - def _AssertFixes(self, original, expected): - """Asserts that the error fixer corrects original to expected.""" - original = self._GetHeader() + original - expected = self._GetHeader() + expected - - actual = StringIO.StringIO() - style_checker = checker.JavaScriptStyleChecker( - error_fixer.ErrorFixer(actual)) - style_checker.CheckLines('testing.js', original, False) - actual.seek(0) - - expected = [x + '\n' for x in expected] - - self.assertListEqual(actual.readlines(), expected) - - def _GetHeader(self): - """Returns a fake header for a JavaScript file.""" - return [ - "// Copyright 2011 Google Inc. All Rights Reserved.", - "", - "/**", - " * @fileoverview Fake file overview.", - " * @author fake@google.com (Fake Person)", - " */", - "" - ] - - -if __name__ == '__main__': - googletest.main() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/full_test.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/full_test.py deleted file mode 100755 index fde9c70b..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/full_test.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Full regression-type (Medium) tests for gjslint. - -Tests every error that can be thrown by gjslint. Based heavily on -devtools/javascript/gpylint/full_test.py -""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import re -import os -import sys -import unittest - -import gflags as flags -import unittest as googletest - -from closure_linter import checker -from closure_linter import errors -from closure_linter import error_check -from closure_linter.common import filetestcase - -_RESOURCE_PREFIX = 'closure_linter/testdata' - -flags.FLAGS.strict = True -flags.FLAGS.custom_jsdoc_tags = ('customtag', 'requires') -flags.FLAGS.closurized_namespaces = ('goog', 'dummy') -flags.FLAGS.limited_doc_files = ('externs.js', 'dummy.js', - 'limited_doc_checks.js') -flags.FLAGS.jslint_error = error_check.Rule.ALL - -# List of files under testdata to test. -# We need to list files explicitly since pyglib can't list directories. -# TODO(user): Figure out how to list the directory. -_TEST_FILES = [ - 'all_js_wrapped.js', - 'blank_lines.js', - 'ends_with_block.js', - 'externs.js', - 'externs_jsdoc.js', - 'goog_scope.js', - 'html_parse_error.html', - 'indentation.js', - 'interface.js', - 'jsdoc.js', - 'limited_doc_checks.js', - 'minimal.js', - 'other.js', - 'provide_blank.js', - 'provide_extra.js', - 'provide_missing.js', - 'require_all_caps.js', - 'require_blank.js', - 'require_extra.js', - 'require_function.js', - 'require_function_missing.js', - 'require_function_through_both.js', - 'require_function_through_namespace.js', - 'require_interface.js', - 'require_interface_base.js', - 'require_lower_case.js', - 'require_missing.js', - 'require_numeric.js', - 'require_provide_blank.js', - 'require_provide_ok.js', - 'require_provide_missing.js', - 'simple.html', - 'spaces.js', - 'tokenizer.js', - 'unparseable.js', - 'unused_private_members.js', - 'utf8.html' - ] - - -class GJsLintTestSuite(unittest.TestSuite): - """Test suite to run a GJsLintTest for each of several files. - - If sys.argv[1:] is non-empty, it is interpreted as a list of filenames in - testdata to test. Otherwise, _TEST_FILES is used. - """ - - def __init__(self, tests=()): - unittest.TestSuite.__init__(self, tests) - - argv = sys.argv and sys.argv[1:] or [] - if argv: - test_files = argv - else: - test_files = _TEST_FILES - for test_file in test_files: - resource_path = os.path.join(_RESOURCE_PREFIX, test_file) - self.addTest(filetestcase.AnnotatedFileTestCase(resource_path, - checker.GJsLintRunner(), errors.ByName)) - -if __name__ == '__main__': - # Don't let main parse args; it happens in the TestSuite. - googletest.main(argv=sys.argv[0:1], defaultTest='GJsLintTestSuite') diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/gjslint.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/gjslint.py deleted file mode 100755 index dcfe09ff..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/gjslint.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env python -# python2.6 for command-line runs using p4lib. pylint: disable-msg=C6301 -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Checks JavaScript files for common style guide violations. - -gjslint.py is designed to be used as a PRESUBMIT script to check for javascript -style guide violations. As of now, it checks for the following violations: - - * Missing and extra spaces - * Lines longer than 80 characters - * Missing newline at end of file - * Missing semicolon after function declaration - * Valid JsDoc including parameter matching - -Someday it will validate to the best of its ability against the entirety of the -JavaScript style guide. - -This file is a front end that parses arguments and flags. The core of the code -is in tokenizer.py and checker.py. -""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import functools -import itertools -import sys -import time - -import gflags as flags - -from closure_linter import checker -from closure_linter import errorrecord -from closure_linter.common import erroraccumulator -from closure_linter.common import simplefileflags as fileflags - -# Attempt import of multiprocessing (should be available in Python 2.6 and up). -try: - # pylint: disable-msg=C6204 - import multiprocessing -except ImportError: - multiprocessing = None - -FLAGS = flags.FLAGS -flags.DEFINE_boolean('unix_mode', False, - 'Whether to emit warnings in standard unix format.') -flags.DEFINE_boolean('beep', True, 'Whether to beep when errors are found.') -flags.DEFINE_boolean('time', False, 'Whether to emit timing statistics.') -flags.DEFINE_boolean('check_html', False, - 'Whether to check javascript in html files.') -flags.DEFINE_boolean('summary', False, - 'Whether to show an error count summary.') -flags.DEFINE_list('additional_extensions', None, 'List of additional file ' - 'extensions (not js) that should be treated as ' - 'JavaScript files.') -flags.DEFINE_boolean('multiprocess', False, - 'Whether to parallalize linting using the ' - 'multiprocessing module. Disabled by default.') - - -GJSLINT_ONLY_FLAGS = ['--unix_mode', '--beep', '--nobeep', '--time', - '--check_html', '--summary'] - - -def _MultiprocessCheckPaths(paths): - """Run _CheckPath over mutltiple processes. - - Tokenization, passes, and checks are expensive operations. Running in a - single process, they can only run on one CPU/core. Instead, - shard out linting over all CPUs with multiprocessing to parallelize. - - Args: - paths: paths to check. - - Yields: - errorrecord.ErrorRecords for any found errors. - """ - - pool = multiprocessing.Pool() - - for results in pool.imap(_CheckPath, paths): - for record in results: - yield record - - pool.close() - pool.join() - - -def _CheckPaths(paths): - """Run _CheckPath on all paths in one thread. - - Args: - paths: paths to check. - - Yields: - errorrecord.ErrorRecords for any found errors. - """ - - for path in paths: - results = _CheckPath(path) - for record in results: - yield record - - -def _CheckPath(path): - """Check a path and return any errors. - - Args: - path: paths to check. - - Returns: - A list of errorrecord.ErrorRecords for any found errors. - """ - - error_accumulator = erroraccumulator.ErrorAccumulator() - style_checker = checker.JavaScriptStyleChecker(error_accumulator) - style_checker.Check(path) - - # Return any errors as error records. - make_error_record = functools.partial(errorrecord.MakeErrorRecord, path) - return map(make_error_record, error_accumulator.GetErrors()) - - -def _GetFilePaths(argv): - suffixes = ['.js'] - if FLAGS.additional_extensions: - suffixes += ['.%s' % ext for ext in FLAGS.additional_extensions] - if FLAGS.check_html: - suffixes += ['.html', '.htm'] - return fileflags.GetFileList(argv, 'JavaScript', suffixes) - - -# Error printing functions - - -def _PrintFileSummary(paths, records): - """Print a detailed summary of the number of errors in each file.""" - - paths = list(paths) - paths.sort() - - for path in paths: - path_errors = [e for e in records if e.path == path] - print '%s: %d' % (path, len(path_errors)) - - -def _PrintFileSeparator(path): - print '----- FILE : %s -----' % path - - -def _PrintSummary(paths, error_records): - """Print a summary of the number of errors and files.""" - - error_count = len(error_records) - all_paths = set(paths) - all_paths_count = len(all_paths) - - if error_count is 0: - print '%d files checked, no errors found.' % all_paths_count - - new_error_count = len([e for e in error_records if e.new_error]) - - error_paths = set([e.path for e in error_records]) - error_paths_count = len(error_paths) - no_error_paths_count = all_paths_count - error_paths_count - - if error_count or new_error_count: - print ('Found %d errors, including %d new errors, in %d files ' - '(%d files OK).' % ( - error_count, - new_error_count, - error_paths_count, - no_error_paths_count)) - - -def _PrintErrorRecords(error_records): - """Print error records strings in the expected format.""" - - current_path = None - for record in error_records: - - if current_path != record.path: - current_path = record.path - if not FLAGS.unix_mode: - _PrintFileSeparator(current_path) - - print record.error_string - - -def _FormatTime(t): - """Formats a duration as a human-readable string. - - Args: - t: A duration in seconds. - - Returns: - A formatted duration string. - """ - if t < 1: - return '%dms' % round(t * 1000) - else: - return '%.2fs' % t - - -def main(argv = None): - """Main function. - - Args: - argv: Sequence of command line arguments. - """ - if argv is None: - argv = flags.FLAGS(sys.argv) - - if FLAGS.time: - start_time = time.time() - - suffixes = ['.js'] - if FLAGS.additional_extensions: - suffixes += ['.%s' % ext for ext in FLAGS.additional_extensions] - if FLAGS.check_html: - suffixes += ['.html', '.htm'] - paths = fileflags.GetFileList(argv, 'JavaScript', suffixes) - - if FLAGS.multiprocess: - records_iter = _MultiprocessCheckPaths(paths) - else: - records_iter = _CheckPaths(paths) - - records_iter, records_iter_copy = itertools.tee(records_iter, 2) - _PrintErrorRecords(records_iter_copy) - - error_records = list(records_iter) - _PrintSummary(paths, error_records) - - exit_code = 0 - - # If there are any errors - if error_records: - exit_code += 1 - - # If there are any new errors - if [r for r in error_records if r.new_error]: - exit_code += 2 - - if exit_code: - if FLAGS.summary: - _PrintFileSummary(paths, error_records) - - if FLAGS.beep: - # Make a beep noise. - sys.stdout.write(chr(7)) - - # Write out instructions for using fixjsstyle script to fix some of the - # reported errors. - fix_args = [] - for flag in sys.argv[1:]: - for f in GJSLINT_ONLY_FLAGS: - if flag.startswith(f): - break - else: - fix_args.append(flag) - - print """ -Some of the errors reported by GJsLint may be auto-fixable using the script -fixjsstyle. Please double check any changes it makes and report any bugs. The -script can be run by executing: - -fixjsstyle %s """ % ' '.join(fix_args) - - if FLAGS.time: - print 'Done in %s.' % _FormatTime(time.time() - start_time) - - sys.exit(exit_code) - - -if __name__ == '__main__': - main() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/indentation.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/indentation.py deleted file mode 100755 index cb97853a..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/indentation.py +++ /dev/null @@ -1,589 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Methods for checking EcmaScript files for indentation issues.""" - -__author__ = ('robbyw@google.com (Robert Walker)') - -from closure_linter import ecmametadatapass -from closure_linter import errors -from closure_linter import javascripttokens -from closure_linter import tokenutil -from closure_linter.common import error -from closure_linter.common import position - -import gflags as flags - -flags.DEFINE_boolean('debug_indentation', False, - 'Whether to print debugging information for indentation.') - - -# Shorthand -Context = ecmametadatapass.EcmaContext -Error = error.Error -Position = position.Position -Type = javascripttokens.JavaScriptTokenType - - -# The general approach: -# -# 1. Build a stack of tokens that can affect indentation. -# For each token, we determine if it is a block or continuation token. -# Some tokens need to be temporarily overwritten in case they are removed -# before the end of the line. -# Much of the work here is determining which tokens to keep on the stack -# at each point. Operators, for example, should be removed once their -# expression or line is gone, while parentheses must stay until the matching -# end parentheses is found. -# -# 2. Given that stack, determine the allowable indentations. -# Due to flexible indentation rules in JavaScript, there may be many -# allowable indentations for each stack. We follows the general -# "no false positives" approach of GJsLint and build the most permissive -# set possible. - - -class TokenInfo(object): - """Stores information about a token. - - Attributes: - token: The token - is_block: Whether the token represents a block indentation. - is_transient: Whether the token should be automatically removed without - finding a matching end token. - overridden_by: TokenInfo for a token that overrides the indentation that - this token would require. - is_permanent_override: Whether the override on this token should persist - even after the overriding token is removed from the stack. For example: - x([ - 1], - 2); - needs this to be set so the last line is not required to be a continuation - indent. - line_number: The effective line number of this token. Will either be the - actual line number or the one before it in the case of a mis-wrapped - operator. - """ - - def __init__(self, token, is_block=False): - """Initializes a TokenInfo object. - - Args: - token: The token - is_block: Whether the token represents a block indentation. - """ - self.token = token - self.overridden_by = None - self.is_permanent_override = False - self.is_block = is_block - self.is_transient = not is_block and not token.type in ( - Type.START_PAREN, Type.START_PARAMETERS) - self.line_number = token.line_number - - def __repr__(self): - result = '\n %s' % self.token - if self.overridden_by: - result = '%s OVERRIDDEN [by "%s"]' % ( - result, self.overridden_by.token.string) - result += ' {is_block: %s, is_transient: %s}' % ( - self.is_block, self.is_transient) - return result - - -class IndentationRules(object): - """EmcaScript indentation rules. - - Can be used to find common indentation errors in JavaScript, ActionScript and - other Ecma like scripting languages. - """ - - def __init__(self): - """Initializes the IndentationRules checker.""" - self._stack = [] - - # Map from line number to number of characters it is off in indentation. - self._start_index_offset = {} - - def Finalize(self): - if self._stack: - old_stack = self._stack - self._stack = [] - raise Exception("INTERNAL ERROR: indentation stack is not empty: %r" % - old_stack) - - def CheckToken(self, token, state): - """Checks a token for indentation errors. - - Args: - token: The current token under consideration - state: Additional information about the current tree state - - Returns: - An error array [error code, error string, error token] if the token is - improperly indented, or None if indentation is correct. - """ - - token_type = token.type - indentation_errors = [] - stack = self._stack - is_first = self._IsFirstNonWhitespaceTokenInLine(token) - - # Add tokens that could decrease indentation before checking. - if token_type == Type.END_PAREN: - self._PopTo(Type.START_PAREN) - - elif token_type == Type.END_PARAMETERS: - self._PopTo(Type.START_PARAMETERS) - - elif token_type == Type.END_BRACKET: - self._PopTo(Type.START_BRACKET) - - elif token_type == Type.END_BLOCK: - start_token = self._PopTo(Type.START_BLOCK) - # Check for required goog.scope comment. - if start_token: - goog_scope = self._GoogScopeOrNone(start_token.token) - if goog_scope is not None: - if not token.line.endswith('; // goog.scope\n'): - if (token.line.find('//') > -1 and - token.line.find('goog.scope') > - token.line.find('//')): - indentation_errors.append([ - errors.MALFORMED_END_OF_SCOPE_COMMENT, - ('Malformed end of goog.scope comment. Please use the ' - 'exact following syntax to close the scope:\n' - '}); // goog.scope'), - token, - Position(token.start_index, token.length)]) - else: - indentation_errors.append([ - errors.MISSING_END_OF_SCOPE_COMMENT, - ('Missing comment for end of goog.scope which opened at line ' - '%d. End the scope with:\n' - '}); // goog.scope' % - (start_token.line_number)), - token, - Position(token.start_index, token.length)]) - - elif token_type == Type.KEYWORD and token.string in ('case', 'default'): - self._Add(self._PopTo(Type.START_BLOCK)) - - elif is_first and token.string == '.': - # This token should have been on the previous line, so treat it as if it - # was there. - info = TokenInfo(token) - info.line_number = token.line_number - 1 - self._Add(info) - - elif token_type == Type.SEMICOLON: - self._PopTransient() - - not_binary_operator = (token_type != Type.OPERATOR or - token.metadata.IsUnaryOperator()) - not_dot = token.string != '.' - if is_first and not_binary_operator and not_dot and token.type not in ( - Type.COMMENT, Type.DOC_PREFIX, Type.STRING_TEXT): - if flags.FLAGS.debug_indentation: - print 'Line #%d: stack %r' % (token.line_number, stack) - - # Ignore lines that start in JsDoc since we don't check them properly yet. - # TODO(robbyw): Support checking JsDoc indentation. - # Ignore lines that start as multi-line strings since indentation is N/A. - # Ignore lines that start with operators since we report that already. - # Ignore lines with tabs since we report that already. - expected = self._GetAllowableIndentations() - actual = self._GetActualIndentation(token) - - # Special case comments describing else, case, and default. Allow them - # to outdent to the parent block. - if token_type in Type.COMMENT_TYPES: - next_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES) - if next_code and next_code.type == Type.END_BLOCK: - next_code = tokenutil.SearchExcept(next_code, Type.NON_CODE_TYPES) - if next_code and next_code.string in ('else', 'case', 'default'): - # TODO(robbyw): This almost certainly introduces false negatives. - expected |= self._AddToEach(expected, -2) - - if actual >= 0 and actual not in expected: - expected = sorted(expected) - indentation_errors.append([ - errors.WRONG_INDENTATION, - 'Wrong indentation: expected any of {%s} but got %d' % ( - ', '.join( - ['%d' % x for x in expected]), actual), - token, - Position(actual, expected[0])]) - self._start_index_offset[token.line_number] = expected[0] - actual - - # Add tokens that could increase indentation. - if token_type == Type.START_BRACKET: - self._Add(TokenInfo(token=token, - is_block=token.metadata.context.type == Context.ARRAY_LITERAL)) - - elif token_type == Type.START_BLOCK or token.metadata.is_implied_block: - self._Add(TokenInfo(token=token, is_block=True)) - - elif token_type in (Type.START_PAREN, Type.START_PARAMETERS): - self._Add(TokenInfo(token=token, is_block=False)) - - elif token_type == Type.KEYWORD and token.string == 'return': - self._Add(TokenInfo(token)) - - elif not token.IsLastInLine() and ( - token.IsAssignment() or token.IsOperator('?')): - self._Add(TokenInfo(token=token)) - - # Handle implied block closes. - if token.metadata.is_implied_block_close: - self._PopToImpliedBlock() - - # Add some tokens only if they appear at the end of the line. - is_last = self._IsLastCodeInLine(token) - if is_last: - if token_type == Type.OPERATOR: - if token.string == ':': - if (stack and stack[-1].token.string == '?'): - # When a ternary : is on a different line than its '?', it doesn't - # add indentation. - if (token.line_number == stack[-1].token.line_number): - self._Add(TokenInfo(token)) - elif token.metadata.context.type == Context.CASE_BLOCK: - # Pop transient tokens from say, line continuations, e.g., - # case x. - # y: - # Want to pop the transient 4 space continuation indent. - self._PopTransient() - # Starting the body of the case statement, which is a type of - # block. - self._Add(TokenInfo(token=token, is_block=True)) - elif token.metadata.context.type == Context.LITERAL_ELEMENT: - # When in an object literal, acts as operator indicating line - # continuations. - self._Add(TokenInfo(token)) - pass - else: - # ':' might also be a statement label, no effect on indentation in - # this case. - pass - - elif token.string != ',': - self._Add(TokenInfo(token)) - else: - # The token is a comma. - if token.metadata.context.type == Context.VAR: - self._Add(TokenInfo(token)) - elif token.metadata.context.type != Context.PARAMETERS: - self._PopTransient() - - elif (token.string.endswith('.') - and token_type in (Type.IDENTIFIER, Type.NORMAL)): - self._Add(TokenInfo(token)) - elif token_type == Type.PARAMETERS and token.string.endswith(','): - # Parameter lists. - self._Add(TokenInfo(token)) - elif token.metadata.is_implied_semicolon: - self._PopTransient() - elif token.IsAssignment(): - self._Add(TokenInfo(token)) - - return indentation_errors - - def _AddToEach(self, original, amount): - """Returns a new set with the given amount added to each element. - - Args: - original: The original set of numbers - amount: The amount to add to each element - - Returns: - A new set containing each element of the original set added to the amount. - """ - return set([x + amount for x in original]) - - _HARD_STOP_TYPES = (Type.START_PAREN, Type.START_PARAMETERS, - Type.START_BRACKET) - - _HARD_STOP_STRINGS = ('return', '?') - - def _IsHardStop(self, token): - """Determines if the given token can have a hard stop after it. - - Hard stops are indentations defined by the position of another token as in - indentation lined up with return, (, [, and ?. - """ - return (token.type in self._HARD_STOP_TYPES or - token.string in self._HARD_STOP_STRINGS or - token.IsAssignment()) - - def _GetAllowableIndentations(self): - """Computes the set of allowable indentations. - - Returns: - The set of allowable indentations, given the current stack. - """ - expected = set([0]) - hard_stops = set([]) - - # Whether the tokens are still in the same continuation, meaning additional - # indentation is optional. As an example: - # x = 5 + - # 6 + - # 7; - # The second '+' does not add any required indentation. - in_same_continuation = False - - for token_info in self._stack: - token = token_info.token - - # Handle normal additive indentation tokens. - if not token_info.overridden_by and token.string != 'return': - if token_info.is_block: - expected = self._AddToEach(expected, 2) - hard_stops = self._AddToEach(hard_stops, 2) - in_same_continuation = False - elif in_same_continuation: - expected |= self._AddToEach(expected, 4) - hard_stops |= self._AddToEach(hard_stops, 4) - else: - expected = self._AddToEach(expected, 4) - hard_stops |= self._AddToEach(hard_stops, 4) - in_same_continuation = True - - # Handle hard stops after (, [, return, =, and ? - if self._IsHardStop(token): - override_is_hard_stop = (token_info.overridden_by and - self._IsHardStop(token_info.overridden_by.token)) - if not override_is_hard_stop: - start_index = token.start_index - if token.line_number in self._start_index_offset: - start_index += self._start_index_offset[token.line_number] - if (token.type in (Type.START_PAREN, Type.START_PARAMETERS) and - not token_info.overridden_by): - hard_stops.add(start_index + 1) - - elif token.string == 'return' and not token_info.overridden_by: - hard_stops.add(start_index + 7) - - elif (token.type == Type.START_BRACKET): - hard_stops.add(start_index + 1) - - elif token.IsAssignment(): - hard_stops.add(start_index + len(token.string) + 1) - - elif token.IsOperator('?') and not token_info.overridden_by: - hard_stops.add(start_index + 2) - - return (expected | hard_stops) or set([0]) - - def _GetActualIndentation(self, token): - """Gets the actual indentation of the line containing the given token. - - Args: - token: Any token on the line. - - Returns: - The actual indentation of the line containing the given token. Returns - -1 if this line should be ignored due to the presence of tabs. - """ - # Move to the first token in the line - token = tokenutil.GetFirstTokenInSameLine(token) - - # If it is whitespace, it is the indentation. - if token.type == Type.WHITESPACE: - if token.string.find('\t') >= 0: - return -1 - else: - return len(token.string) - elif token.type == Type.PARAMETERS: - return len(token.string) - len(token.string.lstrip()) - else: - return 0 - - def _IsFirstNonWhitespaceTokenInLine(self, token): - """Determines if the given token is the first non-space token on its line. - - Args: - token: The token. - - Returns: - True if the token is the first non-whitespace token on its line. - """ - if token.type in (Type.WHITESPACE, Type.BLANK_LINE): - return False - if token.IsFirstInLine(): - return True - return (token.previous and token.previous.IsFirstInLine() and - token.previous.type == Type.WHITESPACE) - - def _IsLastCodeInLine(self, token): - """Determines if the given token is the last code token on its line. - - Args: - token: The token. - - Returns: - True if the token is the last code token on its line. - """ - if token.type in Type.NON_CODE_TYPES: - return False - start_token = token - while True: - token = token.next - if not token or token.line_number != start_token.line_number: - return True - if token.type not in Type.NON_CODE_TYPES: - return False - - def _GoogScopeOrNone(self, token): - """Determines if the given START_BLOCK is part of a goog.scope statement. - - Args: - token: A token of type START_BLOCK. - - Returns: - The goog.scope function call token, or None if such call doesn't exist. - """ - # Search for a goog.scope statement, which will be 5 tokens before the - # block. Illustration of the tokens found prior to the start block: - # goog.scope(function() { - # 5 4 3 21 ^ - - maybe_goog_scope = token - for unused_i in xrange(5): - maybe_goog_scope = (maybe_goog_scope.previous if maybe_goog_scope and - maybe_goog_scope.previous else None) - if maybe_goog_scope and maybe_goog_scope.string == 'goog.scope': - return maybe_goog_scope - - def _Add(self, token_info): - """Adds the given token info to the stack. - - Args: - token_info: The token information to add. - """ - if self._stack and self._stack[-1].token == token_info.token: - # Don't add the same token twice. - return - - if token_info.is_block or token_info.token.type == Type.START_PAREN: - token_info.overridden_by = self._GoogScopeOrNone(token_info.token) - index = 1 - while index <= len(self._stack): - stack_info = self._stack[-index] - stack_token = stack_info.token - - if stack_info.line_number == token_info.line_number: - # In general, tokens only override each other when they are on - # the same line. - stack_info.overridden_by = token_info - if (token_info.token.type == Type.START_BLOCK and - (stack_token.IsAssignment() or - stack_token.type in (Type.IDENTIFIER, Type.START_PAREN))): - # Multi-line blocks have lasting overrides, as in: - # callFn({ - # a: 10 - # }, - # 30); - close_block = token_info.token.metadata.context.end_token - stack_info.is_permanent_override = \ - close_block.line_number != token_info.token.line_number - elif (token_info.token.type == Type.START_BLOCK and - token_info.token.metadata.context.type == Context.BLOCK and - (stack_token.IsAssignment() or - stack_token.type == Type.IDENTIFIER)): - # When starting a function block, the override can transcend lines. - # For example - # long.long.name = function( - # a) { - # In this case the { and the = are on different lines. But the - # override should still apply. - stack_info.overridden_by = token_info - stack_info.is_permanent_override = True - else: - break - index += 1 - - self._stack.append(token_info) - - def _Pop(self): - """Pops the top token from the stack. - - Returns: - The popped token info. - """ - token_info = self._stack.pop() - if token_info.token.type not in (Type.START_BLOCK, Type.START_BRACKET): - # Remove any temporary overrides. - self._RemoveOverrides(token_info) - else: - # For braces and brackets, which can be object and array literals, remove - # overrides when the literal is closed on the same line. - token_check = token_info.token - same_type = token_check.type - goal_type = None - if token_info.token.type == Type.START_BRACKET: - goal_type = Type.END_BRACKET - else: - goal_type = Type.END_BLOCK - line_number = token_info.token.line_number - count = 0 - while token_check and token_check.line_number == line_number: - if token_check.type == goal_type: - count -= 1 - if not count: - self._RemoveOverrides(token_info) - break - if token_check.type == same_type: - count += 1 - token_check = token_check.next - return token_info - - def _PopToImpliedBlock(self): - """Pops the stack until an implied block token is found.""" - while not self._Pop().token.metadata.is_implied_block: - pass - - def _PopTo(self, stop_type): - """Pops the stack until a token of the given type is popped. - - Args: - stop_type: The type of token to pop to. - - Returns: - The token info of the given type that was popped. - """ - last = None - while True: - last = self._Pop() - if last.token.type == stop_type: - break - return last - - def _RemoveOverrides(self, token_info): - """Marks any token that was overridden by this token as active again. - - Args: - token_info: The token that is being removed from the stack. - """ - for stack_token in self._stack: - if (stack_token.overridden_by == token_info and - not stack_token.is_permanent_override): - stack_token.overridden_by = None - - def _PopTransient(self): - """Pops all transient tokens - i.e. not blocks, literals, or parens.""" - while self._stack and self._stack[-1].is_transient: - self._Pop() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascriptlintrules.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascriptlintrules.py deleted file mode 100755 index 0a02a598..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascriptlintrules.py +++ /dev/null @@ -1,539 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2011 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Methods for checking JS files for common style guide violations. - -These style guide violations should only apply to JavaScript and not an Ecma -scripting languages. -""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)', - 'jacobr@google.com (Jacob Richman)') - -import re -from sets import Set -from closure_linter import ecmalintrules -from closure_linter import error_check -from closure_linter import errors -from closure_linter import javascripttokenizer -from closure_linter import javascripttokens -from closure_linter import requireprovidesorter -from closure_linter import tokenutil -from closure_linter.common import error -from closure_linter.common import position - -# Shorthand -Error = error.Error -Position = position.Position -Rule = error_check.Rule -Type = javascripttokens.JavaScriptTokenType - - -class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules): - """JavaScript lint rules that catch JavaScript specific style errors.""" - - def __init__(self, namespaces_info): - """Initializes a JavaScriptLintRules instance.""" - ecmalintrules.EcmaScriptLintRules.__init__(self) - self._namespaces_info = namespaces_info - self._declared_private_member_tokens = {} - self._declared_private_members = Set() - self._used_private_members = Set() - - def HandleMissingParameterDoc(self, token, param_name): - """Handle errors associated with a parameter missing a param tag.""" - self._HandleError(errors.MISSING_PARAMETER_DOCUMENTATION, - 'Missing docs for parameter: "%s"' % param_name, token) - - def __ContainsRecordType(self, token): - """Check whether the given token contains a record type. - - Args: - token: The token being checked - - Returns: - True if the token contains a record type, False otherwise. - """ - # If we see more than one left-brace in the string of an annotation token, - # then there's a record type in there. - return ( - token and token.type == Type.DOC_FLAG and - token.attached_object.type is not None and - token.attached_object.type.find('{') != token.string.rfind('{')) - - def CheckToken(self, token, state): - """Checks a token, given the current parser_state, for warnings and errors. - - Args: - token: The current token under consideration - state: parser_state object that indicates the current state in the page - """ - if self.__ContainsRecordType(token): - # We should bail out and not emit any warnings for this annotation. - # TODO(nicksantos): Support record types for real. - state.GetDocComment().Invalidate() - return - - # Call the base class's CheckToken function. - super(JavaScriptLintRules, self).CheckToken(token, state) - - # Store some convenience variables - namespaces_info = self._namespaces_info - - if error_check.ShouldCheck(Rule.UNUSED_PRIVATE_MEMBERS): - # Find all assignments to private members. - if token.type == Type.SIMPLE_LVALUE: - identifier = token.string - if identifier.endswith('_') and not identifier.endswith('__'): - doc_comment = state.GetDocComment() - suppressed = (doc_comment and doc_comment.HasFlag('suppress') and - doc_comment.GetFlag('suppress').type == 'underscore') - if not suppressed: - # Look for static members defined on a provided namespace. - namespace = namespaces_info.GetClosurizedNamespace(identifier) - provided_namespaces = namespaces_info.GetProvidedNamespaces() - - # Skip cases of this.something_.somethingElse_. - regex = re.compile('^this\.[a-zA-Z_]+$') - if namespace in provided_namespaces or regex.match(identifier): - variable = identifier.split('.')[-1] - self._declared_private_member_tokens[variable] = token - self._declared_private_members.add(variable) - elif not identifier.endswith('__'): - # Consider setting public members of private members to be a usage. - for piece in identifier.split('.'): - if piece.endswith('_'): - self._used_private_members.add(piece) - - # Find all usages of private members. - if token.type == Type.IDENTIFIER: - for piece in token.string.split('.'): - if piece.endswith('_'): - self._used_private_members.add(piece) - - if token.type == Type.DOC_FLAG: - flag = token.attached_object - - if flag.flag_type == 'param' and flag.name_token is not None: - self._CheckForMissingSpaceBeforeToken( - token.attached_object.name_token) - - if (error_check.ShouldCheck(Rule.OPTIONAL_TYPE_MARKER) and - flag.type is not None and flag.name is not None): - # Check for optional marker in type. - if (flag.type.endswith('=') and - not flag.name.startswith('opt_')): - self._HandleError(errors.JSDOC_MISSING_OPTIONAL_PREFIX, - 'Optional parameter name %s must be prefixed ' - 'with opt_.' % flag.name, - token) - elif (not flag.type.endswith('=') and - flag.name.startswith('opt_')): - self._HandleError(errors.JSDOC_MISSING_OPTIONAL_TYPE, - 'Optional parameter %s type must end with =.' % - flag.name, - token) - - if flag.flag_type in state.GetDocFlag().HAS_TYPE: - # Check for both missing type token and empty type braces '{}' - # Missing suppress types are reported separately and we allow enums - # without types. - if (flag.flag_type not in ('suppress', 'enum') and - (not flag.type or flag.type.isspace())): - self._HandleError(errors.MISSING_JSDOC_TAG_TYPE, - 'Missing type in %s tag' % token.string, token) - - elif flag.name_token and flag.type_end_token and tokenutil.Compare( - flag.type_end_token, flag.name_token) > 0: - self._HandleError( - errors.OUT_OF_ORDER_JSDOC_TAG_TYPE, - 'Type should be immediately after %s tag' % token.string, - token) - - elif token.type == Type.DOUBLE_QUOTE_STRING_START: - next_token = token.next - while next_token.type == Type.STRING_TEXT: - if javascripttokenizer.JavaScriptTokenizer.SINGLE_QUOTE.search( - next_token.string): - break - next_token = next_token.next - else: - self._HandleError( - errors.UNNECESSARY_DOUBLE_QUOTED_STRING, - 'Single-quoted string preferred over double-quoted string.', - token, - Position.All(token.string)) - - elif token.type == Type.END_DOC_COMMENT: - doc_comment = state.GetDocComment() - - # When @externs appears in a @fileoverview comment, it should trigger - # the same limited doc checks as a special filename like externs.js. - if doc_comment.HasFlag('fileoverview') and doc_comment.HasFlag('externs'): - self._SetLimitedDocChecks(True) - - if (error_check.ShouldCheck(Rule.BLANK_LINES_AT_TOP_LEVEL) and - not self._is_html and state.InTopLevel() and not state.InBlock()): - - # Check if we're in a fileoverview or constructor JsDoc. - is_constructor = ( - doc_comment.HasFlag('constructor') or - doc_comment.HasFlag('interface')) - is_file_overview = doc_comment.HasFlag('fileoverview') - - # If the comment is not a file overview, and it does not immediately - # precede some code, skip it. - # NOTE: The tokenutil methods are not used here because of their - # behavior at the top of a file. - next_token = token.next - if (not next_token or - (not is_file_overview and next_token.type in Type.NON_CODE_TYPES)): - return - - # Don't require extra blank lines around suppression of extra - # goog.require errors. - if (doc_comment.SuppressionOnly() and - next_token.type == Type.IDENTIFIER and - next_token.string in ['goog.provide', 'goog.require']): - return - - # Find the start of this block (include comments above the block, unless - # this is a file overview). - block_start = doc_comment.start_token - if not is_file_overview: - token = block_start.previous - while token and token.type in Type.COMMENT_TYPES: - block_start = token - token = token.previous - - # Count the number of blank lines before this block. - blank_lines = 0 - token = block_start.previous - while token and token.type in [Type.WHITESPACE, Type.BLANK_LINE]: - if token.type == Type.BLANK_LINE: - # A blank line. - blank_lines += 1 - elif token.type == Type.WHITESPACE and not token.line.strip(): - # A line with only whitespace on it. - blank_lines += 1 - token = token.previous - - # Log errors. - error_message = False - expected_blank_lines = 0 - - if is_file_overview and blank_lines == 0: - error_message = 'Should have a blank line before a file overview.' - expected_blank_lines = 1 - elif is_constructor and blank_lines != 3: - error_message = ( - 'Should have 3 blank lines before a constructor/interface.') - expected_blank_lines = 3 - elif not is_file_overview and not is_constructor and blank_lines != 2: - error_message = 'Should have 2 blank lines between top-level blocks.' - expected_blank_lines = 2 - - if error_message: - self._HandleError( - errors.WRONG_BLANK_LINE_COUNT, error_message, - block_start, Position.AtBeginning(), - expected_blank_lines - blank_lines) - - elif token.type == Type.END_BLOCK: - if state.InFunction() and state.IsFunctionClose(): - is_immediately_called = (token.next and - token.next.type == Type.START_PAREN) - - function = state.GetFunction() - if not self._limited_doc_checks: - if (function.has_return and function.doc and - not is_immediately_called and - not function.doc.HasFlag('return') and - not function.doc.InheritsDocumentation() and - not function.doc.HasFlag('constructor')): - # Check for proper documentation of return value. - self._HandleError( - errors.MISSING_RETURN_DOCUMENTATION, - 'Missing @return JsDoc in function with non-trivial return', - function.doc.end_token, Position.AtBeginning()) - elif (not function.has_return and - not function.has_throw and - function.doc and - function.doc.HasFlag('return') and - not state.InInterfaceMethod()): - return_flag = function.doc.GetFlag('return') - if (return_flag.type is None or ( - 'undefined' not in return_flag.type and - 'void' not in return_flag.type and - '*' not in return_flag.type)): - self._HandleError( - errors.UNNECESSARY_RETURN_DOCUMENTATION, - 'Found @return JsDoc on function that returns nothing', - return_flag.flag_token, Position.AtBeginning()) - - if state.InFunction() and state.IsFunctionClose(): - is_immediately_called = (token.next and - token.next.type == Type.START_PAREN) - if (function.has_this and function.doc and - not function.doc.HasFlag('this') and - not function.is_constructor and - not function.is_interface and - '.prototype.' not in function.name): - self._HandleError( - errors.MISSING_JSDOC_TAG_THIS, - 'Missing @this JsDoc in function referencing "this". (' - 'this usually means you are trying to reference "this" in ' - 'a static function, or you have forgotten to mark a ' - 'constructor with @constructor)', - function.doc.end_token, Position.AtBeginning()) - - elif token.type == Type.IDENTIFIER: - if token.string == 'goog.inherits' and not state.InFunction(): - if state.GetLastNonSpaceToken().line_number == token.line_number: - self._HandleError( - errors.MISSING_LINE, - 'Missing newline between constructor and goog.inherits', - token, - Position.AtBeginning()) - - extra_space = state.GetLastNonSpaceToken().next - while extra_space != token: - if extra_space.type == Type.BLANK_LINE: - self._HandleError( - errors.EXTRA_LINE, - 'Extra line between constructor and goog.inherits', - extra_space) - extra_space = extra_space.next - - # TODO(robbyw): Test the last function was a constructor. - # TODO(robbyw): Test correct @extends and @implements documentation. - - elif (token.string == 'goog.provide' and - not state.InFunction() and - namespaces_info is not None): - namespace = tokenutil.Search(token, Type.STRING_TEXT).string - - # Report extra goog.provide statement. - if namespaces_info.IsExtraProvide(token): - self._HandleError( - errors.EXTRA_GOOG_PROVIDE, - 'Unnecessary goog.provide: ' + namespace, - token, position=Position.AtBeginning()) - - if namespaces_info.IsLastProvide(token): - # Report missing provide statements after the last existing provide. - missing_provides = namespaces_info.GetMissingProvides() - if missing_provides: - self._ReportMissingProvides( - missing_provides, - tokenutil.GetLastTokenInSameLine(token).next, - False) - - # If there are no require statements, missing requires should be - # reported after the last provide. - if not namespaces_info.GetRequiredNamespaces(): - missing_requires = namespaces_info.GetMissingRequires() - if missing_requires: - self._ReportMissingRequires( - missing_requires, - tokenutil.GetLastTokenInSameLine(token).next, - True) - - elif (token.string == 'goog.require' and - not state.InFunction() and - namespaces_info is not None): - namespace = tokenutil.Search(token, Type.STRING_TEXT).string - - # If there are no provide statements, missing provides should be - # reported before the first require. - if (namespaces_info.IsFirstRequire(token) and - not namespaces_info.GetProvidedNamespaces()): - missing_provides = namespaces_info.GetMissingProvides() - if missing_provides: - self._ReportMissingProvides( - missing_provides, - tokenutil.GetFirstTokenInSameLine(token), - True) - - # Report extra goog.require statement. - if namespaces_info.IsExtraRequire(token): - self._HandleError( - errors.EXTRA_GOOG_REQUIRE, - 'Unnecessary goog.require: ' + namespace, - token, position=Position.AtBeginning()) - - # Report missing goog.require statements. - if namespaces_info.IsLastRequire(token): - missing_requires = namespaces_info.GetMissingRequires() - if missing_requires: - self._ReportMissingRequires( - missing_requires, - tokenutil.GetLastTokenInSameLine(token).next, - False) - - elif token.type == Type.OPERATOR: - last_in_line = token.IsLastInLine() - # If the token is unary and appears to be used in a unary context - # it's ok. Otherwise, if it's at the end of the line or immediately - # before a comment, it's ok. - # Don't report an error before a start bracket - it will be reported - # by that token's space checks. - if (not token.metadata.IsUnaryOperator() and not last_in_line - and not token.next.IsComment() - and not token.next.IsOperator(',') - and not token.next.type in (Type.WHITESPACE, Type.END_PAREN, - Type.END_BRACKET, Type.SEMICOLON, - Type.START_BRACKET)): - self._HandleError( - errors.MISSING_SPACE, - 'Missing space after "%s"' % token.string, - token, - Position.AtEnd(token.string)) - elif token.type == Type.WHITESPACE: - first_in_line = token.IsFirstInLine() - last_in_line = token.IsLastInLine() - # Check whitespace length if it's not the first token of the line and - # if it's not immediately before a comment. - if not last_in_line and not first_in_line and not token.next.IsComment(): - # Ensure there is no space after opening parentheses. - if (token.previous.type in (Type.START_PAREN, Type.START_BRACKET, - Type.FUNCTION_NAME) - or token.next.type == Type.START_PARAMETERS): - self._HandleError( - errors.EXTRA_SPACE, - 'Extra space after "%s"' % token.previous.string, - token, - Position.All(token.string)) - - def _ReportMissingProvides(self, missing_provides, token, need_blank_line): - """Reports missing provide statements to the error handler. - - Args: - missing_provides: A list of strings where each string is a namespace that - should be provided, but is not. - token: The token where the error was detected (also where the new provides - will be inserted. - need_blank_line: Whether a blank line needs to be inserted after the new - provides are inserted. May be True, False, or None, where None - indicates that the insert location is unknown. - """ - self._HandleError( - errors.MISSING_GOOG_PROVIDE, - 'Missing the following goog.provide statements:\n' + - '\n'.join(map(lambda x: 'goog.provide(\'%s\');' % x, - sorted(missing_provides))), - token, position=Position.AtBeginning(), - fix_data=(missing_provides, need_blank_line)) - - def _ReportMissingRequires(self, missing_requires, token, need_blank_line): - """Reports missing require statements to the error handler. - - Args: - missing_requires: A list of strings where each string is a namespace that - should be required, but is not. - token: The token where the error was detected (also where the new requires - will be inserted. - need_blank_line: Whether a blank line needs to be inserted before the new - requires are inserted. May be True, False, or None, where None - indicates that the insert location is unknown. - """ - self._HandleError( - errors.MISSING_GOOG_REQUIRE, - 'Missing the following goog.require statements:\n' + - '\n'.join(map(lambda x: 'goog.require(\'%s\');' % x, - sorted(missing_requires))), - token, position=Position.AtBeginning(), - fix_data=(missing_requires, need_blank_line)) - - def Finalize(self, state, tokenizer_mode): - """Perform all checks that need to occur after all lines are processed.""" - # Call the base class's Finalize function. - super(JavaScriptLintRules, self).Finalize(state, tokenizer_mode) - - if error_check.ShouldCheck(Rule.UNUSED_PRIVATE_MEMBERS): - # Report an error for any declared private member that was never used. - unused_private_members = (self._declared_private_members - - self._used_private_members) - - for variable in unused_private_members: - token = self._declared_private_member_tokens[variable] - self._HandleError(errors.UNUSED_PRIVATE_MEMBER, - 'Unused private member: %s.' % token.string, - token) - - # Clear state to prepare for the next file. - self._declared_private_member_tokens = {} - self._declared_private_members = Set() - self._used_private_members = Set() - - namespaces_info = self._namespaces_info - if namespaces_info is not None: - # If there are no provide or require statements, missing provides and - # requires should be reported on line 1. - if (not namespaces_info.GetProvidedNamespaces() and - not namespaces_info.GetRequiredNamespaces()): - missing_provides = namespaces_info.GetMissingProvides() - if missing_provides: - self._ReportMissingProvides( - missing_provides, state.GetFirstToken(), None) - - missing_requires = namespaces_info.GetMissingRequires() - if missing_requires: - self._ReportMissingRequires( - missing_requires, state.GetFirstToken(), None) - - self._CheckSortedRequiresProvides(state.GetFirstToken()) - - def _CheckSortedRequiresProvides(self, token): - """Checks that all goog.require and goog.provide statements are sorted. - - Note that this method needs to be run after missing statements are added to - preserve alphabetical order. - - Args: - token: The first token in the token stream. - """ - sorter = requireprovidesorter.RequireProvideSorter() - provides_result = sorter.CheckProvides(token) - if provides_result: - self._HandleError( - errors.GOOG_PROVIDES_NOT_ALPHABETIZED, - 'goog.provide classes must be alphabetized. The correct code is:\n' + - '\n'.join( - map(lambda x: 'goog.provide(\'%s\');' % x, provides_result[1])), - provides_result[0], - position=Position.AtBeginning(), - fix_data=provides_result[0]) - - requires_result = sorter.CheckRequires(token) - if requires_result: - self._HandleError( - errors.GOOG_REQUIRES_NOT_ALPHABETIZED, - 'goog.require classes must be alphabetized. The correct code is:\n' + - '\n'.join( - map(lambda x: 'goog.require(\'%s\');' % x, requires_result[1])), - requires_result[0], - position=Position.AtBeginning(), - fix_data=requires_result[0]) - - def GetLongLineExceptions(self): - """Gets a list of regexps for lines which can be longer than the limit.""" - return [ - re.compile('.*// @suppress longLineCheck$'), - re.compile('goog\.require\(.+\);?\s*$'), - re.compile('goog\.provide\(.+\);?\s*$') - ] diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascriptstatetracker.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascriptstatetracker.py deleted file mode 100755 index 2ce5c02c..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascriptstatetracker.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Parser for JavaScript files.""" - - - -from closure_linter import javascripttokens -from closure_linter import statetracker -from closure_linter import tokenutil - -# Shorthand -Type = javascripttokens.JavaScriptTokenType - - -class JsDocFlag(statetracker.DocFlag): - """Javascript doc flag object. - - Attribute: - flag_type: param, return, define, type, etc. - flag_token: The flag token. - type_start_token: The first token specifying the flag JS type, - including braces. - type_end_token: The last token specifying the flag JS type, - including braces. - type: The JavaScript type spec. - name_token: The token specifying the flag name. - name: The flag name - description_start_token: The first token in the description. - description_end_token: The end token in the description. - description: The description. - """ - - # Please keep these lists alphabetized. - - # Some projects use the following extensions to JsDoc. - # TODO(robbyw): determine which of these, if any, should be illegal. - EXTENDED_DOC = frozenset([ - 'class', 'code', 'desc', 'final', 'hidden', 'inheritDoc', 'link', - 'meaning', 'protected', 'notypecheck', 'throws']) - - LEGAL_DOC = EXTENDED_DOC | statetracker.DocFlag.LEGAL_DOC - - def __init__(self, flag_token): - """Creates the JsDocFlag object and attaches it to the given start token. - - Args: - flag_token: The starting token of the flag. - """ - statetracker.DocFlag.__init__(self, flag_token) - - -class JavaScriptStateTracker(statetracker.StateTracker): - """JavaScript state tracker. - - Inherits from the core EcmaScript StateTracker adding extra state tracking - functionality needed for JavaScript. - """ - - def __init__(self): - """Initializes a JavaScript token stream state tracker.""" - statetracker.StateTracker.__init__(self, JsDocFlag) - - def InTopLevel(self): - """Compute whether we are at the top level in the class. - - This function call is language specific. In some languages like - JavaScript, a function is top level if it is not inside any parenthesis. - In languages such as ActionScript, a function is top level if it is directly - within a class. - - Returns: - Whether we are at the top level in the class. - """ - return not self.InParentheses() - - def GetBlockType(self, token): - """Determine the block type given a START_BLOCK token. - - Code blocks come after parameters, keywords like else, and closing parens. - - Args: - token: The current token. Can be assumed to be type START_BLOCK - Returns: - Code block type for current token. - """ - last_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES, None, - True) - if last_code.type in (Type.END_PARAMETERS, Type.END_PAREN, - Type.KEYWORD) and not last_code.IsKeyword('return'): - return self.CODE - else: - return self.OBJECT_LITERAL - - def HandleToken(self, token, last_non_space_token): - """Handles the given token and updates state. - - Args: - token: The token to handle. - last_non_space_token: - """ - super(JavaScriptStateTracker, self).HandleToken(token, - last_non_space_token) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascripttokenizer.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascripttokenizer.py deleted file mode 100755 index 98f91849..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascripttokenizer.py +++ /dev/null @@ -1,363 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Regular expression based JavaScript parsing classes.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import copy -import re - -from closure_linter import javascripttokens -from closure_linter.common import matcher -from closure_linter.common import tokenizer - -# Shorthand -Type = javascripttokens.JavaScriptTokenType -Matcher = matcher.Matcher - - -class JavaScriptModes(object): - """Enumeration of the different matcher modes used for JavaScript.""" - TEXT_MODE = 'text' - SINGLE_QUOTE_STRING_MODE = 'single_quote_string' - DOUBLE_QUOTE_STRING_MODE = 'double_quote_string' - BLOCK_COMMENT_MODE = 'block_comment' - DOC_COMMENT_MODE = 'doc_comment' - DOC_COMMENT_LEX_SPACES_MODE = 'doc_comment_spaces' - LINE_COMMENT_MODE = 'line_comment' - PARAMETER_MODE = 'parameter' - FUNCTION_MODE = 'function' - - -class JavaScriptTokenizer(tokenizer.Tokenizer): - """JavaScript tokenizer. - - Convert JavaScript code in to an array of tokens. - """ - - # Useful patterns for JavaScript parsing. - IDENTIFIER_CHAR = r'A-Za-z0-9_$.' - - # Number patterns based on: - # http://www.mozilla.org/js/language/js20-2000-07/formal/lexer-grammar.html - MANTISSA = r""" - (\d+(?!\.)) | # Matches '10' - (\d+\.(?!\d)) | # Matches '10.' - (\d*\.\d+) # Matches '.5' or '10.5' - """ - DECIMAL_LITERAL = r'(%s)([eE][-+]?\d+)?' % MANTISSA - HEX_LITERAL = r'0[xX][0-9a-fA-F]+' - NUMBER = re.compile(r""" - ((%s)|(%s)) - """ % (HEX_LITERAL, DECIMAL_LITERAL), re.VERBOSE) - - # Strings come in three parts - first we match the start of the string, then - # the contents, then the end. The contents consist of any character except a - # backslash or end of string, or a backslash followed by any character, or a - # backslash followed by end of line to support correct parsing of multi-line - # strings. - SINGLE_QUOTE = re.compile(r"'") - SINGLE_QUOTE_TEXT = re.compile(r"([^'\\]|\\(.|$))+") - DOUBLE_QUOTE = re.compile(r'"') - DOUBLE_QUOTE_TEXT = re.compile(r'([^"\\]|\\(.|$))+') - - START_SINGLE_LINE_COMMENT = re.compile(r'//') - END_OF_LINE_SINGLE_LINE_COMMENT = re.compile(r'//$') - - START_DOC_COMMENT = re.compile(r'/\*\*') - START_BLOCK_COMMENT = re.compile(r'/\*') - END_BLOCK_COMMENT = re.compile(r'\*/') - BLOCK_COMMENT_TEXT = re.compile(r'([^*]|\*(?!/))+') - - # Comment text is anything that we are not going to parse into another special - # token like (inline) flags or end comments. Complicated regex to match - # most normal characters, and '*', '{', '}', and '@' when we are sure that - # it is safe. Expression [^*{\s]@ must come first, or the other options will - # match everything before @, and we won't match @'s that aren't part of flags - # like in email addresses in the @author tag. - DOC_COMMENT_TEXT = re.compile(r'([^*{}\s]@|[^*{}@]|\*(?!/))+') - DOC_COMMENT_NO_SPACES_TEXT = re.compile(r'([^*{}\s]@|[^*{}@\s]|\*(?!/))+') - - # Match the prefix ' * ' that starts every line of jsdoc. Want to include - # spaces after the '*', but nothing else that occurs after a '*', and don't - # want to match the '*' in '*/'. - DOC_PREFIX = re.compile(r'\s*\*(\s+|(?!/))') - - START_BLOCK = re.compile('{') - END_BLOCK = re.compile('}') - - REGEX_CHARACTER_CLASS = r""" - \[ # Opening bracket - ([^\]\\]|\\.)* # Anything but a ] or \, - # or a backslash followed by anything - \] # Closing bracket - """ - # We ensure the regex is followed by one of the above tokens to avoid - # incorrectly parsing something like x / y / z as x REGEX(/ y /) z - POST_REGEX_LIST = [ - ';', ',', r'\.', r'\)', r'\]', '$', r'\/\/', r'\/\*', ':', '}'] - - REGEX = re.compile(r""" - / # opening slash - (?!\*) # not the start of a comment - (\\.|[^\[\/\\]|(%s))* # a backslash followed by anything, - # or anything but a / or [ or \, - # or a character class - / # closing slash - [gimsx]* # optional modifiers - (?=\s*(%s)) - """ % (REGEX_CHARACTER_CLASS, '|'.join(POST_REGEX_LIST)), - re.VERBOSE) - - ANYTHING = re.compile(r'.*') - PARAMETERS = re.compile(r'[^\)]+') - CLOSING_PAREN_WITH_SPACE = re.compile(r'\)\s*') - - FUNCTION_DECLARATION = re.compile(r'\bfunction\b') - - OPENING_PAREN = re.compile(r'\(') - CLOSING_PAREN = re.compile(r'\)') - - OPENING_BRACKET = re.compile(r'\[') - CLOSING_BRACKET = re.compile(r'\]') - - # We omit these JS keywords from the list: - # function - covered by FUNCTION_DECLARATION. - # delete, in, instanceof, new, typeof - included as operators. - # this - included in identifiers. - # null, undefined - not included, should go in some "special constant" list. - KEYWORD_LIST = ['break', 'case', 'catch', 'continue', 'default', 'do', 'else', - 'finally', 'for', 'if', 'return', 'switch', 'throw', 'try', 'var', - 'while', 'with'] - # Match a keyword string followed by a non-identifier character in order to - # not match something like doSomething as do + Something. - KEYWORD = re.compile('(%s)((?=[^%s])|$)' % ( - '|'.join(KEYWORD_LIST), IDENTIFIER_CHAR)) - - # List of regular expressions to match as operators. Some notes: for our - # purposes, the comma behaves similarly enough to a normal operator that we - # include it here. r'\bin\b' actually matches 'in' surrounded by boundary - # characters - this may not match some very esoteric uses of the in operator. - # Operators that are subsets of larger operators must come later in this list - # for proper matching, e.g., '>>' must come AFTER '>>>'. - OPERATOR_LIST = [',', r'\+\+', '===', '!==', '>>>=', '>>>', '==', '>=', '<=', - '!=', '<<=', '>>=', '<<', '>>', '>', '<', r'\+=', r'\+', - '--', '\^=', '-=', '-', '/=', '/', r'\*=', r'\*', '%=', '%', - '&&', r'\|\|', '&=', '&', r'\|=', r'\|', '=', '!', ':', '\?', - r'\bdelete\b', r'\bin\b', r'\binstanceof\b', r'\bnew\b', - r'\btypeof\b', r'\bvoid\b'] - OPERATOR = re.compile('|'.join(OPERATOR_LIST)) - - WHITESPACE = re.compile(r'\s+') - SEMICOLON = re.compile(r';') - # Technically JavaScript identifiers can't contain '.', but we treat a set of - # nested identifiers as a single identifier. - NESTED_IDENTIFIER = r'[a-zA-Z_$][%s.]*' % IDENTIFIER_CHAR - IDENTIFIER = re.compile(NESTED_IDENTIFIER) - - SIMPLE_LVALUE = re.compile(r""" - (?P%s) # a valid identifier - (?=\s* # optional whitespace - \= # look ahead to equal sign - (?!=)) # not follwed by equal - """ % NESTED_IDENTIFIER, re.VERBOSE) - - # A doc flag is a @ sign followed by non-space characters that appears at the - # beginning of the line, after whitespace, or after a '{'. The look-behind - # check is necessary to not match someone@google.com as a flag. - DOC_FLAG = re.compile(r'(^|(?<=\s))@(?P[a-zA-Z]+)') - # To properly parse parameter names, we need to tokenize whitespace into a - # token. - DOC_FLAG_LEX_SPACES = re.compile(r'(^|(?<=\s))@(?P%s)\b' % - '|'.join(['param'])) - - DOC_INLINE_FLAG = re.compile(r'(?<={)@(?P[a-zA-Z]+)') - - # Star followed by non-slash, i.e a star that does not end a comment. - # This is used for TYPE_GROUP below. - SAFE_STAR = r'(\*(?!/))' - - COMMON_DOC_MATCHERS = [ - # Find the end of the comment. - Matcher(END_BLOCK_COMMENT, Type.END_DOC_COMMENT, - JavaScriptModes.TEXT_MODE), - - # Tokenize documented flags like @private. - Matcher(DOC_INLINE_FLAG, Type.DOC_INLINE_FLAG), - Matcher(DOC_FLAG_LEX_SPACES, Type.DOC_FLAG, - JavaScriptModes.DOC_COMMENT_LEX_SPACES_MODE), - - # Encountering a doc flag should leave lex spaces mode. - Matcher(DOC_FLAG, Type.DOC_FLAG, JavaScriptModes.DOC_COMMENT_MODE), - - # Tokenize braces so we can find types. - Matcher(START_BLOCK, Type.DOC_START_BRACE), - Matcher(END_BLOCK, Type.DOC_END_BRACE), - Matcher(DOC_PREFIX, Type.DOC_PREFIX, None, True)] - - - # The token matcher groups work as follows: it is an list of Matcher objects. - # The matchers will be tried in this order, and the first to match will be - # returned. Hence the order is important because the matchers that come first - # overrule the matchers that come later. - JAVASCRIPT_MATCHERS = { - # Matchers for basic text mode. - JavaScriptModes.TEXT_MODE: [ - # Check a big group - strings, starting comments, and regexes - all - # of which could be intertwined. 'string with /regex/', - # /regex with 'string'/, /* comment with /regex/ and string */ (and so - # on) - Matcher(START_DOC_COMMENT, Type.START_DOC_COMMENT, - JavaScriptModes.DOC_COMMENT_MODE), - Matcher(START_BLOCK_COMMENT, Type.START_BLOCK_COMMENT, - JavaScriptModes.BLOCK_COMMENT_MODE), - Matcher(END_OF_LINE_SINGLE_LINE_COMMENT, - Type.START_SINGLE_LINE_COMMENT), - Matcher(START_SINGLE_LINE_COMMENT, Type.START_SINGLE_LINE_COMMENT, - JavaScriptModes.LINE_COMMENT_MODE), - Matcher(SINGLE_QUOTE, Type.SINGLE_QUOTE_STRING_START, - JavaScriptModes.SINGLE_QUOTE_STRING_MODE), - Matcher(DOUBLE_QUOTE, Type.DOUBLE_QUOTE_STRING_START, - JavaScriptModes.DOUBLE_QUOTE_STRING_MODE), - Matcher(REGEX, Type.REGEX), - - # Next we check for start blocks appearing outside any of the items - # above. - Matcher(START_BLOCK, Type.START_BLOCK), - Matcher(END_BLOCK, Type.END_BLOCK), - - # Then we search for function declarations. - Matcher(FUNCTION_DECLARATION, Type.FUNCTION_DECLARATION, - JavaScriptModes.FUNCTION_MODE), - - # Next, we convert non-function related parens to tokens. - Matcher(OPENING_PAREN, Type.START_PAREN), - Matcher(CLOSING_PAREN, Type.END_PAREN), - - # Next, we convert brackets to tokens. - Matcher(OPENING_BRACKET, Type.START_BRACKET), - Matcher(CLOSING_BRACKET, Type.END_BRACKET), - - # Find numbers. This has to happen before operators because scientific - # notation numbers can have + and - in them. - Matcher(NUMBER, Type.NUMBER), - - # Find operators and simple assignments - Matcher(SIMPLE_LVALUE, Type.SIMPLE_LVALUE), - Matcher(OPERATOR, Type.OPERATOR), - - # Find key words and whitespace. - Matcher(KEYWORD, Type.KEYWORD), - Matcher(WHITESPACE, Type.WHITESPACE), - - # Find identifiers. - Matcher(IDENTIFIER, Type.IDENTIFIER), - - # Finally, we convert semicolons to tokens. - Matcher(SEMICOLON, Type.SEMICOLON)], - - # Matchers for single quote strings. - JavaScriptModes.SINGLE_QUOTE_STRING_MODE: [ - Matcher(SINGLE_QUOTE_TEXT, Type.STRING_TEXT), - Matcher(SINGLE_QUOTE, Type.SINGLE_QUOTE_STRING_END, - JavaScriptModes.TEXT_MODE)], - - # Matchers for double quote strings. - JavaScriptModes.DOUBLE_QUOTE_STRING_MODE: [ - Matcher(DOUBLE_QUOTE_TEXT, Type.STRING_TEXT), - Matcher(DOUBLE_QUOTE, Type.DOUBLE_QUOTE_STRING_END, - JavaScriptModes.TEXT_MODE)], - - # Matchers for block comments. - JavaScriptModes.BLOCK_COMMENT_MODE: [ - # First we check for exiting a block comment. - Matcher(END_BLOCK_COMMENT, Type.END_BLOCK_COMMENT, - JavaScriptModes.TEXT_MODE), - - # Match non-comment-ending text.. - Matcher(BLOCK_COMMENT_TEXT, Type.COMMENT)], - - # Matchers for doc comments. - JavaScriptModes.DOC_COMMENT_MODE: COMMON_DOC_MATCHERS + [ - Matcher(DOC_COMMENT_TEXT, Type.COMMENT)], - - JavaScriptModes.DOC_COMMENT_LEX_SPACES_MODE: COMMON_DOC_MATCHERS + [ - Matcher(WHITESPACE, Type.COMMENT), - Matcher(DOC_COMMENT_NO_SPACES_TEXT, Type.COMMENT)], - - # Matchers for single line comments. - JavaScriptModes.LINE_COMMENT_MODE: [ - # We greedy match until the end of the line in line comment mode. - Matcher(ANYTHING, Type.COMMENT, JavaScriptModes.TEXT_MODE)], - - # Matchers for code after the function keyword. - JavaScriptModes.FUNCTION_MODE: [ - # Must match open paren before anything else and move into parameter - # mode, otherwise everything inside the parameter list is parsed - # incorrectly. - Matcher(OPENING_PAREN, Type.START_PARAMETERS, - JavaScriptModes.PARAMETER_MODE), - Matcher(WHITESPACE, Type.WHITESPACE), - Matcher(IDENTIFIER, Type.FUNCTION_NAME)], - - # Matchers for function parameters - JavaScriptModes.PARAMETER_MODE: [ - # When in function parameter mode, a closing paren is treated specially. - # Everything else is treated as lines of parameters. - Matcher(CLOSING_PAREN_WITH_SPACE, Type.END_PARAMETERS, - JavaScriptModes.TEXT_MODE), - Matcher(PARAMETERS, Type.PARAMETERS, JavaScriptModes.PARAMETER_MODE)]} - - # When text is not matched, it is given this default type based on mode. - # If unspecified in this map, the default default is Type.NORMAL. - JAVASCRIPT_DEFAULT_TYPES = { - JavaScriptModes.DOC_COMMENT_MODE: Type.COMMENT, - JavaScriptModes.DOC_COMMENT_LEX_SPACES_MODE: Type.COMMENT - } - - def __init__(self, parse_js_doc = True): - """Create a tokenizer object. - - Args: - parse_js_doc: Whether to do detailed parsing of javascript doc comments, - or simply treat them as normal comments. Defaults to parsing JsDoc. - """ - matchers = self.JAVASCRIPT_MATCHERS - if not parse_js_doc: - # Make a copy so the original doesn't get modified. - matchers = copy.deepcopy(matchers) - matchers[JavaScriptModes.DOC_COMMENT_MODE] = matchers[ - JavaScriptModes.BLOCK_COMMENT_MODE] - - tokenizer.Tokenizer.__init__(self, JavaScriptModes.TEXT_MODE, matchers, - self.JAVASCRIPT_DEFAULT_TYPES) - - def _CreateToken(self, string, token_type, line, line_number, values=None): - """Creates a new JavaScriptToken object. - - Args: - string: The string of input the token contains. - token_type: The type of token. - line: The text of the line this token is in. - line_number: The line number of the token. - values: A dict of named values within the token. For instance, a - function declaration may have a value called 'name' which captures the - name of the function. - """ - return javascripttokens.JavaScriptToken(string, token_type, line, - line_number, values) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascripttokens.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascripttokens.py deleted file mode 100755 index f46d4e17..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/javascripttokens.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Classes to represent JavaScript tokens.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -from closure_linter.common import tokens - -class JavaScriptTokenType(tokens.TokenType): - """Enumeration of JavaScript token types, and useful sets of token types.""" - NUMBER = 'number' - START_SINGLE_LINE_COMMENT = '//' - START_BLOCK_COMMENT = '/*' - START_DOC_COMMENT = '/**' - END_BLOCK_COMMENT = '*/' - END_DOC_COMMENT = 'doc */' - COMMENT = 'comment' - SINGLE_QUOTE_STRING_START = "'string" - SINGLE_QUOTE_STRING_END = "string'" - DOUBLE_QUOTE_STRING_START = '"string' - DOUBLE_QUOTE_STRING_END = 'string"' - STRING_TEXT = 'string' - START_BLOCK = '{' - END_BLOCK = '}' - START_PAREN = '(' - END_PAREN = ')' - START_BRACKET = '[' - END_BRACKET = ']' - REGEX = '/regex/' - FUNCTION_DECLARATION = 'function(...)' - FUNCTION_NAME = 'function functionName(...)' - START_PARAMETERS = 'startparams(' - PARAMETERS = 'pa,ra,ms' - END_PARAMETERS = ')endparams' - SEMICOLON = ';' - DOC_FLAG = '@flag' - DOC_INLINE_FLAG = '{@flag ...}' - DOC_START_BRACE = 'doc {' - DOC_END_BRACE = 'doc }' - DOC_PREFIX = 'comment prefix: * ' - SIMPLE_LVALUE = 'lvalue=' - KEYWORD = 'keyword' - OPERATOR = 'operator' - IDENTIFIER = 'identifier' - - STRING_TYPES = frozenset([ - SINGLE_QUOTE_STRING_START, SINGLE_QUOTE_STRING_END, - DOUBLE_QUOTE_STRING_START, DOUBLE_QUOTE_STRING_END, STRING_TEXT]) - - COMMENT_TYPES = frozenset([START_SINGLE_LINE_COMMENT, COMMENT, - START_BLOCK_COMMENT, START_DOC_COMMENT, - END_BLOCK_COMMENT, END_DOC_COMMENT, - DOC_START_BRACE, DOC_END_BRACE, - DOC_FLAG, DOC_INLINE_FLAG, DOC_PREFIX]) - - FLAG_DESCRIPTION_TYPES = frozenset([ - DOC_INLINE_FLAG, COMMENT, DOC_START_BRACE, DOC_END_BRACE]) - - FLAG_ENDING_TYPES = frozenset([DOC_FLAG, END_DOC_COMMENT]) - - NON_CODE_TYPES = COMMENT_TYPES | frozenset([ - tokens.TokenType.WHITESPACE, tokens.TokenType.BLANK_LINE]) - - UNARY_OPERATORS = ['!', 'new', 'delete', 'typeof', 'void'] - - UNARY_OK_OPERATORS = ['--', '++', '-', '+'] + UNARY_OPERATORS - - UNARY_POST_OPERATORS = ['--', '++'] - - # An expression ender is any token that can end an object - i.e. we could have - # x.y or [1, 2], or (10 + 9) or {a: 10}. - EXPRESSION_ENDER_TYPES = [tokens.TokenType.NORMAL, IDENTIFIER, NUMBER, - SIMPLE_LVALUE, END_BRACKET, END_PAREN, END_BLOCK, - SINGLE_QUOTE_STRING_END, DOUBLE_QUOTE_STRING_END] - - -class JavaScriptToken(tokens.Token): - """JavaScript token subclass of Token, provides extra instance checks. - - The following token types have data in attached_object: - - All JsDoc flags: a parser.JsDocFlag object. - """ - - def IsKeyword(self, keyword): - """Tests if this token is the given keyword. - - Args: - keyword: The keyword to compare to. - - Returns: - True if this token is a keyword token with the given name. - """ - return self.type == JavaScriptTokenType.KEYWORD and self.string == keyword - - def IsOperator(self, operator): - """Tests if this token is the given operator. - - Args: - operator: The operator to compare to. - - Returns: - True if this token is a operator token with the given name. - """ - return self.type == JavaScriptTokenType.OPERATOR and self.string == operator - - def IsAssignment(self): - """Tests if this token is an assignment operator. - - Returns: - True if this token is an assignment operator. - """ - return (self.type == JavaScriptTokenType.OPERATOR and - self.string.endswith('=') and - self.string not in ('==', '!=', '>=', '<=', '===', '!==')) - - def IsComment(self): - """Tests if this token is any part of a comment. - - Returns: - True if this token is any part of a comment. - """ - return self.type in JavaScriptTokenType.COMMENT_TYPES - - def IsCode(self): - """Tests if this token is code, as opposed to a comment or whitespace.""" - return self.type not in JavaScriptTokenType.NON_CODE_TYPES - - def __repr__(self): - return '' % (self.line_number, - self.type, self.string, - self.values, - self.metadata) diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/not_strict_test.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/not_strict_test.py deleted file mode 100755 index 8df8efcd..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/not_strict_test.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2011 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Tests for gjslint --nostrict. - -Tests errors that can be thrown by gjslint when not in strict mode. -""" - - - -import os -import sys -import unittest - -import gflags as flags -import unittest as googletest - -from closure_linter import checker -from closure_linter import errors -from closure_linter.common import filetestcase - -_RESOURCE_PREFIX = 'closure_linter/testdata' - -flags.FLAGS.strict = False -flags.FLAGS.custom_jsdoc_tags = ('customtag', 'requires') -flags.FLAGS.closurized_namespaces = ('goog', 'dummy') -flags.FLAGS.limited_doc_files = ('externs.js', 'dummy.js', - 'limited_doc_checks.js') - - -# List of files under testdata to test. -# We need to list files explicitly since pyglib can't list directories. -_TEST_FILES = [ - 'not_strict.js' - ] - - -class GJsLintTestSuite(unittest.TestSuite): - """Test suite to run a GJsLintTest for each of several files. - - If sys.argv[1:] is non-empty, it is interpreted as a list of filenames in - testdata to test. Otherwise, _TEST_FILES is used. - """ - - def __init__(self, tests=()): - unittest.TestSuite.__init__(self, tests) - - argv = sys.argv and sys.argv[1:] or [] - if argv: - test_files = argv - else: - test_files = _TEST_FILES - for test_file in test_files: - resource_path = os.path.join(_RESOURCE_PREFIX, test_file) - self.addTest(filetestcase.AnnotatedFileTestCase(resource_path, - checker.GJsLintRunner(), - errors.ByName)) - -if __name__ == '__main__': - # Don't let main parse args; it happens in the TestSuite. - googletest.main(argv=sys.argv[0:1], defaultTest='GJsLintTestSuite') diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/requireprovidesorter.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/requireprovidesorter.py deleted file mode 100755 index 6dda3aeb..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/requireprovidesorter.py +++ /dev/null @@ -1,272 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2011 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Contains logic for sorting goog.provide and goog.require statements. - -Closurized JavaScript files use goog.provide and goog.require statements at the -top of the file to manage dependencies. These statements should be sorted -alphabetically, however, it is common for them to be accompanied by inline -comments or suppression annotations. In order to sort these statements without -disrupting their comments and annotations, the association between statements -and comments/annotations must be maintained while sorting. - - RequireProvideSorter: Handles checking/fixing of provide/require statements. -""" - - - -from closure_linter import javascripttokens -from closure_linter import tokenutil - -# Shorthand -Type = javascripttokens.JavaScriptTokenType - - -class RequireProvideSorter(object): - """Checks for and fixes alphabetization of provide and require statements. - - When alphabetizing, comments on the same line or comments directly above a - goog.provide or goog.require statement are associated with that statement and - stay with the statement as it gets sorted. - """ - - def CheckProvides(self, token): - """Checks alphabetization of goog.provide statements. - - Iterates over tokens in given token stream, identifies goog.provide tokens, - and checks that they occur in alphabetical order by the object being - provided. - - Args: - token: A token in the token stream before any goog.provide tokens. - - Returns: - A tuple containing the first provide token in the token stream and a list - of provided objects sorted alphabetically. For example: - - (JavaScriptToken, ['object.a', 'object.b', ...]) - - None is returned if all goog.provide statements are already sorted. - """ - provide_tokens = self._GetRequireOrProvideTokens(token, 'goog.provide') - provide_strings = self._GetRequireOrProvideTokenStrings(provide_tokens) - sorted_provide_strings = sorted(provide_strings) - if provide_strings != sorted_provide_strings: - return [provide_tokens[0], sorted_provide_strings] - return None - - def CheckRequires(self, token): - """Checks alphabetization of goog.require statements. - - Iterates over tokens in given token stream, identifies goog.require tokens, - and checks that they occur in alphabetical order by the dependency being - required. - - Args: - token: A token in the token stream before any goog.require tokens. - - Returns: - A tuple containing the first require token in the token stream and a list - of required dependencies sorted alphabetically. For example: - - (JavaScriptToken, ['object.a', 'object.b', ...]) - - None is returned if all goog.require statements are already sorted. - """ - require_tokens = self._GetRequireOrProvideTokens(token, 'goog.require') - require_strings = self._GetRequireOrProvideTokenStrings(require_tokens) - sorted_require_strings = sorted(require_strings) - if require_strings != sorted_require_strings: - return (require_tokens[0], sorted_require_strings) - return None - - def FixProvides(self, token): - """Sorts goog.provide statements in the given token stream alphabetically. - - Args: - token: The first token in the token stream. - """ - self._FixProvidesOrRequires( - self._GetRequireOrProvideTokens(token, 'goog.provide')) - - def FixRequires(self, token): - """Sorts goog.require statements in the given token stream alphabetically. - - Args: - token: The first token in the token stream. - """ - self._FixProvidesOrRequires( - self._GetRequireOrProvideTokens(token, 'goog.require')) - - def _FixProvidesOrRequires(self, tokens): - """Sorts goog.provide or goog.require statements. - - Args: - tokens: A list of goog.provide or goog.require tokens in the order they - appear in the token stream. i.e. the first token in this list must - be the first goog.provide or goog.require token. - """ - strings = self._GetRequireOrProvideTokenStrings(tokens) - sorted_strings = sorted(strings) - - # Make a separate pass to remove any blank lines between goog.require/ - # goog.provide tokens. - first_token = tokens[0] - last_token = tokens[-1] - i = last_token - while i != first_token: - if i.type is Type.BLANK_LINE: - tokenutil.DeleteToken(i) - i = i.previous - - # A map from required/provided object name to tokens that make up the line - # it was on, including any comments immediately before it or after it on the - # same line. - tokens_map = self._GetTokensMap(tokens) - - # Iterate over the map removing all tokens. - for name in tokens_map: - tokens_to_delete = tokens_map[name] - for i in tokens_to_delete: - tokenutil.DeleteToken(i) - - # Re-add all tokens in the map in alphabetical order. - insert_after = tokens[0].previous - for string in sorted_strings: - for i in tokens_map[string]: - tokenutil.InsertTokenAfter(i, insert_after) - insert_after = i - - def _GetRequireOrProvideTokens(self, token, token_string): - """Gets all goog.provide or goog.require tokens in the given token stream. - - Args: - token: The first token in the token stream. - token_string: One of 'goog.provide' or 'goog.require' to indicate which - tokens to find. - - Returns: - A list of goog.provide or goog.require tokens in the order they appear in - the token stream. - """ - tokens = [] - while token: - if token.type == Type.IDENTIFIER: - if token.string == token_string: - tokens.append(token) - elif token.string not in ['goog.require', 'goog.provide']: - # The goog.provide and goog.require identifiers are at the top of the - # file. So if any other identifier is encountered, return. - break - token = token.next - - return tokens - - def _GetRequireOrProvideTokenStrings(self, tokens): - """Gets a list of strings corresponding to the given list of tokens. - - The string will be the next string in the token stream after each token in - tokens. This is used to find the object being provided/required by a given - goog.provide or goog.require token. - - Args: - tokens: A list of goog.provide or goog.require tokens. - - Returns: - A list of object names that are being provided or required by the given - list of tokens. For example: - - ['object.a', 'object.c', 'object.b'] - """ - token_strings = [] - for token in tokens: - name = tokenutil.Search(token, Type.STRING_TEXT).string - token_strings.append(name) - return token_strings - - def _GetTokensMap(self, tokens): - """Gets a map from object name to tokens associated with that object. - - Starting from the goog.provide/goog.require token, searches backwards in the - token stream for any lines that start with a comment. These lines are - associated with the goog.provide/goog.require token. Also associates any - tokens on the same line as the goog.provide/goog.require token with that - token. - - Args: - tokens: A list of goog.provide or goog.require tokens. - - Returns: - A dictionary that maps object names to the tokens associated with the - goog.provide or goog.require of that object name. For example: - - { - 'object.a': [JavaScriptToken, JavaScriptToken, ...], - 'object.b': [...] - } - - The list of tokens includes any comment lines above the goog.provide or - goog.require statement and everything after the statement on the same - line. For example, all of the following would be associated with - 'object.a': - - /** @suppress {extraRequire} */ - goog.require('object.a'); // Some comment. - """ - tokens_map = {} - for token in tokens: - object_name = tokenutil.Search(token, Type.STRING_TEXT).string - # If the previous line starts with a comment, presume that the comment - # relates to the goog.require or goog.provide and keep them together when - # sorting. - first_token = token - previous_first_token = tokenutil.GetFirstTokenInPreviousLine(first_token) - while previous_first_token.IsAnyType(Type.COMMENT_TYPES): - first_token = previous_first_token - previous_first_token = tokenutil.GetFirstTokenInPreviousLine( - first_token) - - # Find the last token on the line. - last_token = tokenutil.GetLastTokenInSameLine(token) - - all_tokens = self._GetTokenList(first_token, last_token) - tokens_map[object_name] = all_tokens - return tokens_map - - def _GetTokenList(self, first_token, last_token): - """Gets a list of all tokens from first_token to last_token, inclusive. - - Args: - first_token: The first token to get. - last_token: The last token to get. - - Returns: - A list of all tokens between first_token and last_token, including both - first_token and last_token. - - Raises: - Exception: If the token stream ends before last_token is reached. - """ - token_list = [] - token = first_token - while token != last_token: - if not token: - raise Exception('ran out of tokens') - token_list.append(token) - token = token.next - token_list.append(last_token) - - return token_list diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/requireprovidesorter_test.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/requireprovidesorter_test.py deleted file mode 100755 index d1d61dc5..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/requireprovidesorter_test.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Unit tests for RequireProvideSorter.""" - - - -import unittest as googletest -from closure_linter import ecmametadatapass -from closure_linter import javascripttokenizer -from closure_linter import javascripttokens -from closure_linter import requireprovidesorter - -# pylint: disable-msg=C6409 -TokenType = javascripttokens.JavaScriptTokenType - - -class RequireProvideSorterTest(googletest.TestCase): - """Tests for RequireProvideSorter.""" - - _tokenizer = javascripttokenizer.JavaScriptTokenizer() - _metadata_pass = ecmametadatapass.EcmaMetaDataPass() - - def testFixRequires_removeBlankLines(self): - """Tests that blank lines are omitted in sorted goog.require statements.""" - input_lines = [ - 'goog.provide(\'package.subpackage.Whatever\');', - '', - 'goog.require(\'package.subpackage.ClassB\');', - '', - 'goog.require(\'package.subpackage.ClassA\');' - ] - expected_lines = [ - 'goog.provide(\'package.subpackage.Whatever\');', - '', - 'goog.require(\'package.subpackage.ClassA\');', - 'goog.require(\'package.subpackage.ClassB\');' - ] - token = self._tokenizer.TokenizeFile(input_lines) - self._metadata_pass.Reset() - self._metadata_pass.Process(token) - - sorter = requireprovidesorter.RequireProvideSorter() - sorter.FixRequires(token) - - self.assertEquals(expected_lines, self._GetLines(token)) - - def _GetLines(self, token): - """Returns an array of lines based on the specified token stream.""" - lines = [] - line = '' - while token: - line += token.string - if token.IsLastInLine(): - lines.append(line) - line = '' - token = token.next - return lines - -if __name__ == '__main__': - googletest.main() diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/statetracker.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/statetracker.py deleted file mode 100755 index 52e86a90..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/statetracker.py +++ /dev/null @@ -1,1008 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Light weight EcmaScript state tracker that reads tokens and tracks state.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import re - -from closure_linter import javascripttokenizer -from closure_linter import javascripttokens -from closure_linter import tokenutil - -# Shorthand -Type = javascripttokens.JavaScriptTokenType - - -class DocFlag(object): - """Generic doc flag object. - - Attribute: - flag_type: param, return, define, type, etc. - flag_token: The flag token. - type_start_token: The first token specifying the flag type, - including braces. - type_end_token: The last token specifying the flag type, - including braces. - type: The type spec. - name_token: The token specifying the flag name. - name: The flag name - description_start_token: The first token in the description. - description_end_token: The end token in the description. - description: The description. - """ - - # Please keep these lists alphabetized. - - # The list of standard jsdoc tags is from - STANDARD_DOC = frozenset([ - 'author', - 'bug', - 'const', - 'constructor', - 'define', - 'deprecated', - 'enum', - 'export', - 'extends', - 'externs', - 'fileoverview', - 'implements', - 'implicitCast', - 'interface', - 'lends', - 'license', - 'noalias', - 'nocompile', - 'nosideeffects', - 'override', - 'owner', - 'param', - 'preserve', - 'private', - 'return', - 'see', - 'supported', - 'template', - 'this', - 'type', - 'typedef', - ]) - - ANNOTATION = frozenset(['preserveTry', 'suppress']) - - LEGAL_DOC = STANDARD_DOC | ANNOTATION - - # Includes all Closure Compiler @suppress types. - # Not all of these annotations are interpreted by Closure Linter. - # - # Specific cases: - # - accessControls is supported by the compiler at the expression - # and method level to suppress warnings about private/protected - # access (method level applies to all references in the method). - # The linter mimics the compiler behavior. - SUPPRESS_TYPES = frozenset([ - 'accessControls', - 'ambiguousFunctionDecl', - 'checkRegExp', - 'checkTypes', - 'checkVars', - 'const', - 'constantProperty', - 'deprecated', - 'duplicate', - 'es5Strict', - 'externsValidation', - 'extraProvide', - 'extraRequire', - 'fileoverviewTags', - 'globalThis', - 'internetExplorerChecks', - 'invalidCasts', - 'missingProperties', - 'missingProvide', - 'missingRequire', - 'nonStandardJsDocs', - 'strictModuleDepCheck', - 'tweakValidation', - 'typeInvalidation', - 'undefinedNames', - 'undefinedVars', - 'underscore', - 'unknownDefines', - 'uselessCode', - 'visibility', - 'with']) - - HAS_DESCRIPTION = frozenset([ - 'define', 'deprecated', 'desc', 'fileoverview', 'license', 'param', - 'preserve', 'return', 'supported']) - - HAS_TYPE = frozenset([ - 'define', 'enum', 'extends', 'implements', 'param', 'return', 'type', - 'suppress']) - - TYPE_ONLY = frozenset(['enum', 'extends', 'implements', 'suppress', 'type']) - - HAS_NAME = frozenset(['param']) - - EMPTY_COMMENT_LINE = re.compile(r'^\s*\*?\s*$') - EMPTY_STRING = re.compile(r'^\s*$') - - def __init__(self, flag_token): - """Creates the DocFlag object and attaches it to the given start token. - - Args: - flag_token: The starting token of the flag. - """ - self.flag_token = flag_token - self.flag_type = flag_token.string.strip().lstrip('@') - - # Extract type, if applicable. - self.type = None - self.type_start_token = None - self.type_end_token = None - if self.flag_type in self.HAS_TYPE: - brace = tokenutil.SearchUntil(flag_token, [Type.DOC_START_BRACE], - Type.FLAG_ENDING_TYPES) - if brace: - end_token, contents = _GetMatchingEndBraceAndContents(brace) - self.type = contents - self.type_start_token = brace - self.type_end_token = end_token - elif (self.flag_type in self.TYPE_ONLY and - flag_token.next.type not in Type.FLAG_ENDING_TYPES): - self.type_start_token = flag_token.next - self.type_end_token, self.type = _GetEndTokenAndContents( - self.type_start_token) - if self.type is not None: - self.type = self.type.strip() - - # Extract name, if applicable. - self.name_token = None - self.name = None - if self.flag_type in self.HAS_NAME: - # Handle bad case, name could be immediately after flag token. - self.name_token = _GetNextIdentifierToken(flag_token) - - # Handle good case, if found token is after type start, look for - # identifier after type end, since types contain identifiers. - if (self.type and self.name_token and - tokenutil.Compare(self.name_token, self.type_start_token) > 0): - self.name_token = _GetNextIdentifierToken(self.type_end_token) - - if self.name_token: - self.name = self.name_token.string - - # Extract description, if applicable. - self.description_start_token = None - self.description_end_token = None - self.description = None - if self.flag_type in self.HAS_DESCRIPTION: - search_start_token = flag_token - if self.name_token and self.type_end_token: - if tokenutil.Compare(self.type_end_token, self.name_token) > 0: - search_start_token = self.type_end_token - else: - search_start_token = self.name_token - elif self.name_token: - search_start_token = self.name_token - elif self.type: - search_start_token = self.type_end_token - - interesting_token = tokenutil.Search(search_start_token, - Type.FLAG_DESCRIPTION_TYPES | Type.FLAG_ENDING_TYPES) - if interesting_token.type in Type.FLAG_DESCRIPTION_TYPES: - self.description_start_token = interesting_token - self.description_end_token, self.description = ( - _GetEndTokenAndContents(interesting_token)) - - -class DocComment(object): - """JavaScript doc comment object. - - Attributes: - ordered_params: Ordered list of parameters documented. - start_token: The token that starts the doc comment. - end_token: The token that ends the doc comment. - suppressions: Map of suppression type to the token that added it. - """ - def __init__(self, start_token): - """Create the doc comment object. - - Args: - start_token: The first token in the doc comment. - """ - self.__params = {} - self.ordered_params = [] - self.__flags = {} - self.start_token = start_token - self.end_token = None - self.suppressions = {} - self.invalidated = False - - def Invalidate(self): - """Indicate that the JSDoc is well-formed but we had problems parsing it. - - This is a short-circuiting mechanism so that we don't emit false - positives about well-formed doc comments just because we don't support - hot new syntaxes. - """ - self.invalidated = True - - def IsInvalidated(self): - """Test whether Invalidate() has been called.""" - return self.invalidated - - def AddParam(self, name, param_type): - """Add a new documented parameter. - - Args: - name: The name of the parameter to document. - param_type: The parameter's declared JavaScript type. - """ - self.ordered_params.append(name) - self.__params[name] = param_type - - def AddSuppression(self, token): - """Add a new error suppression flag. - - Args: - token: The suppression flag token. - """ - #TODO(user): Error if no braces - brace = tokenutil.SearchUntil(token, [Type.DOC_START_BRACE], - [Type.DOC_FLAG]) - if brace: - end_token, contents = _GetMatchingEndBraceAndContents(brace) - for suppression in contents.split('|'): - self.suppressions[suppression] = token - - def SuppressionOnly(self): - """Returns whether this comment contains only suppression flags.""" - for flag_type in self.__flags.keys(): - if flag_type != 'suppress': - return False - return True - - def AddFlag(self, flag): - """Add a new document flag. - - Args: - flag: DocFlag object. - """ - self.__flags[flag.flag_type] = flag - - def InheritsDocumentation(self): - """Test if the jsdoc implies documentation inheritance. - - Returns: - True if documentation may be pulled off the superclass. - """ - return self.HasFlag('inheritDoc') or self.HasFlag('override') - - def HasFlag(self, flag_type): - """Test if the given flag has been set. - - Args: - flag_type: The type of the flag to check. - - Returns: - True if the flag is set. - """ - return flag_type in self.__flags - - def GetFlag(self, flag_type): - """Gets the last flag of the given type. - - Args: - flag_type: The type of the flag to get. - - Returns: - The last instance of the given flag type in this doc comment. - """ - return self.__flags[flag_type] - - def CompareParameters(self, params): - """Computes the edit distance and list from the function params to the docs. - - Uses the Levenshtein edit distance algorithm, with code modified from - http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#Python - - Args: - params: The parameter list for the function declaration. - - Returns: - The edit distance, the edit list. - """ - source_len, target_len = len(self.ordered_params), len(params) - edit_lists = [[]] - distance = [[]] - for i in range(target_len+1): - edit_lists[0].append(['I'] * i) - distance[0].append(i) - - for j in range(1, source_len+1): - edit_lists.append([['D'] * j]) - distance.append([j]) - - for i in range(source_len): - for j in range(target_len): - cost = 1 - if self.ordered_params[i] == params[j]: - cost = 0 - - deletion = distance[i][j+1] + 1 - insertion = distance[i+1][j] + 1 - substitution = distance[i][j] + cost - - edit_list = None - best = None - if deletion <= insertion and deletion <= substitution: - # Deletion is best. - best = deletion - edit_list = list(edit_lists[i][j+1]) - edit_list.append('D') - - elif insertion <= substitution: - # Insertion is best. - best = insertion - edit_list = list(edit_lists[i+1][j]) - edit_list.append('I') - edit_lists[i+1].append(edit_list) - - else: - # Substitution is best. - best = substitution - edit_list = list(edit_lists[i][j]) - if cost: - edit_list.append('S') - else: - edit_list.append('=') - - edit_lists[i+1].append(edit_list) - distance[i+1].append(best) - - return distance[source_len][target_len], edit_lists[source_len][target_len] - - def __repr__(self): - """Returns a string representation of this object. - - Returns: - A string representation of this object. - """ - return '' % (str(self.__params), str(self.__flags)) - - -# -# Helper methods used by DocFlag and DocComment to parse out flag information. -# - - -def _GetMatchingEndBraceAndContents(start_brace): - """Returns the matching end brace and contents between the two braces. - - If any FLAG_ENDING_TYPE token is encountered before a matching end brace, then - that token is used as the matching ending token. Contents will have all - comment prefixes stripped out of them, and all comment prefixes in between the - start and end tokens will be split out into separate DOC_PREFIX tokens. - - Args: - start_brace: The DOC_START_BRACE token immediately before desired contents. - - Returns: - The matching ending token (DOC_END_BRACE or FLAG_ENDING_TYPE) and a string - of the contents between the matching tokens, minus any comment prefixes. - """ - open_count = 1 - close_count = 0 - contents = [] - - # We don't consider the start brace part of the type string. - token = start_brace.next - while open_count != close_count: - if token.type == Type.DOC_START_BRACE: - open_count += 1 - elif token.type == Type.DOC_END_BRACE: - close_count += 1 - - if token.type != Type.DOC_PREFIX: - contents.append(token.string) - - if token.type in Type.FLAG_ENDING_TYPES: - break - token = token.next - - #Don't include the end token (end brace, end doc comment, etc.) in type. - token = token.previous - contents = contents[:-1] - - return token, ''.join(contents) - - -def _GetNextIdentifierToken(start_token): - """Searches for and returns the first identifier at the beginning of a token. - - Searches each token after the start to see if it starts with an identifier. - If found, will split the token into at most 3 piecies: leading whitespace, - identifier, rest of token, returning the identifier token. If no identifier is - found returns None and changes no tokens. Search is abandoned when a - FLAG_ENDING_TYPE token is found. - - Args: - start_token: The token to start searching after. - - Returns: - The identifier token is found, None otherwise. - """ - token = start_token.next - - while token and not token.type in Type.FLAG_ENDING_TYPES: - match = javascripttokenizer.JavaScriptTokenizer.IDENTIFIER.match( - token.string) - if (match is not None and token.type == Type.COMMENT and - len(token.string) == len(match.group(0))): - return token - - token = token.next - - return None - - -def _GetEndTokenAndContents(start_token): - """Returns last content token and all contents before FLAG_ENDING_TYPE token. - - Comment prefixes are split into DOC_PREFIX tokens and stripped from the - returned contents. - - Args: - start_token: The token immediately before the first content token. - - Returns: - The last content token and a string of all contents including start and - end tokens, with comment prefixes stripped. - """ - iterator = start_token - last_line = iterator.line_number - last_token = None - contents = '' - doc_depth = 0 - while not iterator.type in Type.FLAG_ENDING_TYPES or doc_depth > 0: - if (iterator.IsFirstInLine() and - DocFlag.EMPTY_COMMENT_LINE.match(iterator.line)): - # If we have a blank comment line, consider that an implicit - # ending of the description. This handles a case like: - # - # * @return {boolean} True - # * - # * Note: This is a sentence. - # - # The note is not part of the @return description, but there was - # no definitive ending token. Rather there was a line containing - # only a doc comment prefix or whitespace. - break - - # b/2983692 - # don't prematurely match against a @flag if inside a doc flag - # need to think about what is the correct behavior for unterminated - # inline doc flags - if (iterator.type == Type.DOC_START_BRACE and - iterator.next.type == Type.DOC_INLINE_FLAG): - doc_depth += 1 - elif (iterator.type == Type.DOC_END_BRACE and - doc_depth > 0): - doc_depth -= 1 - - if iterator.type in Type.FLAG_DESCRIPTION_TYPES: - contents += iterator.string - last_token = iterator - - iterator = iterator.next - if iterator.line_number != last_line: - contents += '\n' - last_line = iterator.line_number - - end_token = last_token - if DocFlag.EMPTY_STRING.match(contents): - contents = None - else: - # Strip trailing newline. - contents = contents[:-1] - - return end_token, contents - - -class Function(object): - """Data about a JavaScript function. - - Attributes: - block_depth: Block depth the function began at. - doc: The DocComment associated with the function. - has_return: If the function has a return value. - has_this: If the function references the 'this' object. - is_assigned: If the function is part of an assignment. - is_constructor: If the function is a constructor. - name: The name of the function, whether given in the function keyword or - as the lvalue the function is assigned to. - """ - - def __init__(self, block_depth, is_assigned, doc, name): - self.block_depth = block_depth - self.is_assigned = is_assigned - self.is_constructor = doc and doc.HasFlag('constructor') - self.is_interface = doc and doc.HasFlag('interface') - self.has_return = False - self.has_throw = False - self.has_this = False - self.name = name - self.doc = doc - - -class StateTracker(object): - """EcmaScript state tracker. - - Tracks block depth, function names, etc. within an EcmaScript token stream. - """ - - OBJECT_LITERAL = 'o' - CODE = 'c' - - def __init__(self, doc_flag=DocFlag): - """Initializes a JavaScript token stream state tracker. - - Args: - doc_flag: An optional custom DocFlag used for validating - documentation flags. - """ - self._doc_flag = doc_flag - self.Reset() - - def Reset(self): - """Resets the state tracker to prepare for processing a new page.""" - self._block_depth = 0 - self._is_block_close = False - self._paren_depth = 0 - self._functions = [] - self._functions_by_name = {} - self._last_comment = None - self._doc_comment = None - self._cumulative_params = None - self._block_types = [] - self._last_non_space_token = None - self._last_line = None - self._first_token = None - self._documented_identifiers = set() - - def InFunction(self): - """Returns true if the current token is within a function. - - Returns: - True if the current token is within a function. - """ - return bool(self._functions) - - def InConstructor(self): - """Returns true if the current token is within a constructor. - - Returns: - True if the current token is within a constructor. - """ - return self.InFunction() and self._functions[-1].is_constructor - - def InInterfaceMethod(self): - """Returns true if the current token is within an interface method. - - Returns: - True if the current token is within an interface method. - """ - if self.InFunction(): - if self._functions[-1].is_interface: - return True - else: - name = self._functions[-1].name - prototype_index = name.find('.prototype.') - if prototype_index != -1: - class_function_name = name[0:prototype_index] - if (class_function_name in self._functions_by_name and - self._functions_by_name[class_function_name].is_interface): - return True - - return False - - def InTopLevelFunction(self): - """Returns true if the current token is within a top level function. - - Returns: - True if the current token is within a top level function. - """ - return len(self._functions) == 1 and self.InTopLevel() - - def InAssignedFunction(self): - """Returns true if the current token is within a function variable. - - Returns: - True if if the current token is within a function variable - """ - return self.InFunction() and self._functions[-1].is_assigned - - def IsFunctionOpen(self): - """Returns true if the current token is a function block open. - - Returns: - True if the current token is a function block open. - """ - return (self._functions and - self._functions[-1].block_depth == self._block_depth - 1) - - def IsFunctionClose(self): - """Returns true if the current token is a function block close. - - Returns: - True if the current token is a function block close. - """ - return (self._functions and - self._functions[-1].block_depth == self._block_depth) - - def InBlock(self): - """Returns true if the current token is within a block. - - Returns: - True if the current token is within a block. - """ - return bool(self._block_depth) - - def IsBlockClose(self): - """Returns true if the current token is a block close. - - Returns: - True if the current token is a block close. - """ - return self._is_block_close - - def InObjectLiteral(self): - """Returns true if the current token is within an object literal. - - Returns: - True if the current token is within an object literal. - """ - return self._block_depth and self._block_types[-1] == self.OBJECT_LITERAL - - def InObjectLiteralDescendant(self): - """Returns true if the current token has an object literal ancestor. - - Returns: - True if the current token has an object literal ancestor. - """ - return self.OBJECT_LITERAL in self._block_types - - def InParentheses(self): - """Returns true if the current token is within parentheses. - - Returns: - True if the current token is within parentheses. - """ - return bool(self._paren_depth) - - def InTopLevel(self): - """Whether we are at the top level in the class. - - This function call is language specific. In some languages like - JavaScript, a function is top level if it is not inside any parenthesis. - In languages such as ActionScript, a function is top level if it is directly - within a class. - """ - raise TypeError('Abstract method InTopLevel not implemented') - - def GetBlockType(self, token): - """Determine the block type given a START_BLOCK token. - - Code blocks come after parameters, keywords like else, and closing parens. - - Args: - token: The current token. Can be assumed to be type START_BLOCK. - Returns: - Code block type for current token. - """ - raise TypeError('Abstract method GetBlockType not implemented') - - def GetParams(self): - """Returns the accumulated input params as an array. - - In some EcmasSript languages, input params are specified like - (param:Type, param2:Type2, ...) - in other they are specified just as - (param, param2) - We handle both formats for specifying parameters here and leave - it to the compilers for each language to detect compile errors. - This allows more code to be reused between lint checkers for various - EcmaScript languages. - - Returns: - The accumulated input params as an array. - """ - params = [] - if self._cumulative_params: - params = re.compile(r'\s+').sub('', self._cumulative_params).split(',') - # Strip out the type from parameters of the form name:Type. - params = map(lambda param: param.split(':')[0], params) - - return params - - def GetLastComment(self): - """Return the last plain comment that could be used as documentation. - - Returns: - The last plain comment that could be used as documentation. - """ - return self._last_comment - - def GetDocComment(self): - """Return the most recent applicable documentation comment. - - Returns: - The last applicable documentation comment. - """ - return self._doc_comment - - def HasDocComment(self, identifier): - """Returns whether the identifier has been documented yet. - - Args: - identifier: The identifier. - - Returns: - Whether the identifier has been documented yet. - """ - return identifier in self._documented_identifiers - - def InDocComment(self): - """Returns whether the current token is in a doc comment. - - Returns: - Whether the current token is in a doc comment. - """ - return self._doc_comment and self._doc_comment.end_token is None - - def GetDocFlag(self): - """Returns the current documentation flags. - - Returns: - The current documentation flags. - """ - return self._doc_flag - - def IsTypeToken(self, t): - if self.InDocComment() and t.type not in (Type.START_DOC_COMMENT, - Type.DOC_FLAG, Type.DOC_INLINE_FLAG, Type.DOC_PREFIX): - f = tokenutil.SearchUntil(t, [Type.DOC_FLAG], [Type.START_DOC_COMMENT], - None, True) - if f and f.attached_object.type_start_token is not None: - return (tokenutil.Compare(t, f.attached_object.type_start_token) > 0 and - tokenutil.Compare(t, f.attached_object.type_end_token) < 0) - return False - - def GetFunction(self): - """Return the function the current code block is a part of. - - Returns: - The current Function object. - """ - if self._functions: - return self._functions[-1] - - def GetBlockDepth(self): - """Return the block depth. - - Returns: - The current block depth. - """ - return self._block_depth - - def GetLastNonSpaceToken(self): - """Return the last non whitespace token.""" - return self._last_non_space_token - - def GetLastLine(self): - """Return the last line.""" - return self._last_line - - def GetFirstToken(self): - """Return the very first token in the file.""" - return self._first_token - - def HandleToken(self, token, last_non_space_token): - """Handles the given token and updates state. - - Args: - token: The token to handle. - last_non_space_token: - """ - self._is_block_close = False - - if not self._first_token: - self._first_token = token - - # Track block depth. - type = token.type - if type == Type.START_BLOCK: - self._block_depth += 1 - - # Subclasses need to handle block start very differently because - # whether a block is a CODE or OBJECT_LITERAL block varies significantly - # by language. - self._block_types.append(self.GetBlockType(token)) - - # Track block depth. - elif type == Type.END_BLOCK: - self._is_block_close = not self.InObjectLiteral() - self._block_depth -= 1 - self._block_types.pop() - - # Track parentheses depth. - elif type == Type.START_PAREN: - self._paren_depth += 1 - - # Track parentheses depth. - elif type == Type.END_PAREN: - self._paren_depth -= 1 - - elif type == Type.COMMENT: - self._last_comment = token.string - - elif type == Type.START_DOC_COMMENT: - self._last_comment = None - self._doc_comment = DocComment(token) - - elif type == Type.END_DOC_COMMENT: - self._doc_comment.end_token = token - - elif type in (Type.DOC_FLAG, Type.DOC_INLINE_FLAG): - flag = self._doc_flag(token) - token.attached_object = flag - self._doc_comment.AddFlag(flag) - - if flag.flag_type == 'param' and flag.name: - self._doc_comment.AddParam(flag.name, flag.type) - elif flag.flag_type == 'suppress': - self._doc_comment.AddSuppression(token) - - elif type == Type.FUNCTION_DECLARATION: - last_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES, None, - True) - doc = None - # Only functions outside of parens are eligible for documentation. - if not self._paren_depth: - doc = self._doc_comment - - name = '' - is_assigned = last_code and (last_code.IsOperator('=') or - last_code.IsOperator('||') or last_code.IsOperator('&&') or - (last_code.IsOperator(':') and not self.InObjectLiteral())) - if is_assigned: - # TODO(robbyw): This breaks for x[2] = ... - # Must use loop to find full function name in the case of line-wrapped - # declarations (bug 1220601) like: - # my.function.foo. - # bar = function() ... - identifier = tokenutil.Search(last_code, Type.SIMPLE_LVALUE, None, True) - while identifier and identifier.type in ( - Type.IDENTIFIER, Type.SIMPLE_LVALUE): - name = identifier.string + name - # Traverse behind us, skipping whitespace and comments. - while True: - identifier = identifier.previous - if not identifier or not identifier.type in Type.NON_CODE_TYPES: - break - - else: - next_token = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES) - while next_token and next_token.IsType(Type.FUNCTION_NAME): - name += next_token.string - next_token = tokenutil.Search(next_token, Type.FUNCTION_NAME, 2) - - function = Function(self._block_depth, is_assigned, doc, name) - self._functions.append(function) - self._functions_by_name[name] = function - - elif type == Type.START_PARAMETERS: - self._cumulative_params = '' - - elif type == Type.PARAMETERS: - self._cumulative_params += token.string - - elif type == Type.KEYWORD and token.string == 'return': - next_token = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES) - if not next_token.IsType(Type.SEMICOLON): - function = self.GetFunction() - if function: - function.has_return = True - - elif type == Type.KEYWORD and token.string == 'throw': - function = self.GetFunction() - if function: - function.has_throw = True - - elif type == Type.SIMPLE_LVALUE: - identifier = token.values['identifier'] - jsdoc = self.GetDocComment() - if jsdoc: - self._documented_identifiers.add(identifier) - - self._HandleIdentifier(identifier, True) - - elif type == Type.IDENTIFIER: - self._HandleIdentifier(token.string, False) - - # Detect documented non-assignments. - next_token = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES) - if next_token.IsType(Type.SEMICOLON): - if (self._last_non_space_token and - self._last_non_space_token.IsType(Type.END_DOC_COMMENT)): - self._documented_identifiers.add(token.string) - - def _HandleIdentifier(self, identifier, is_assignment): - """Process the given identifier. - - Currently checks if it references 'this' and annotates the function - accordingly. - - Args: - identifier: The identifer to process. - is_assignment: Whether the identifer is being written to. - """ - if identifier == 'this' or identifier.startswith('this.'): - function = self.GetFunction() - if function: - function.has_this = True - - - def HandleAfterToken(self, token): - """Handle updating state after a token has been checked. - - This function should be used for destructive state changes such as - deleting a tracked object. - - Args: - token: The token to handle. - """ - type = token.type - if type == Type.SEMICOLON or type == Type.END_PAREN or ( - type == Type.END_BRACKET and - self._last_non_space_token.type not in ( - Type.SINGLE_QUOTE_STRING_END, Type.DOUBLE_QUOTE_STRING_END)): - # We end on any numeric array index, but keep going for string based - # array indices so that we pick up manually exported identifiers. - self._doc_comment = None - self._last_comment = None - - elif type == Type.END_BLOCK: - self._doc_comment = None - self._last_comment = None - - if self.InFunction() and self.IsFunctionClose(): - # TODO(robbyw): Detect the function's name for better errors. - self._functions.pop() - - elif type == Type.END_PARAMETERS and self._doc_comment: - self._doc_comment = None - self._last_comment = None - - if not token.IsAnyType(Type.WHITESPACE, Type.BLANK_LINE): - self._last_non_space_token = token - - self._last_line = token.line diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/tokenutil.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/tokenutil.py deleted file mode 100755 index 92ff16b3..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/closure_linter/tokenutil.py +++ /dev/null @@ -1,374 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -"""Token utility functions.""" - -__author__ = ('robbyw@google.com (Robert Walker)', - 'ajp@google.com (Andy Perelson)') - -import copy - -from closure_linter import javascripttokens -from closure_linter.common import tokens - -# Shorthand -JavaScriptToken = javascripttokens.JavaScriptToken -Type = tokens.TokenType - - -def GetFirstTokenInSameLine(token): - """Returns the first token in the same line as token. - - Args: - token: Any token in the line. - - Returns: - The first token in the same line as token. - """ - while not token.IsFirstInLine(): - token = token.previous - return token - - -def GetFirstTokenInPreviousLine(token): - """Returns the first token in the previous line as token. - - Args: - token: Any token in the line. - - Returns: - The first token in the previous line as token, or None if token is on the - first line. - """ - first_in_line = GetFirstTokenInSameLine(token) - if first_in_line.previous: - return GetFirstTokenInSameLine(first_in_line.previous) - - return None - - -def GetLastTokenInSameLine(token): - """Returns the last token in the same line as token. - - Args: - token: Any token in the line. - - Returns: - The last token in the same line as token. - """ - while not token.IsLastInLine(): - token = token.next - return token - - -def GetAllTokensInSameLine(token): - """Returns all tokens in the same line as the given token. - - Args: - token: Any token in the line. - - Returns: - All tokens on the same line as the given token. - """ - first_token = GetFirstTokenInSameLine(token) - last_token = GetLastTokenInSameLine(token) - - tokens_in_line = [] - while first_token != last_token: - tokens_in_line.append(first_token) - first_token = first_token.next - tokens_in_line.append(last_token) - - return tokens_in_line - - -def CustomSearch(start_token, func, end_func=None, distance=None, - reverse=False): - """Returns the first token where func is True within distance of this token. - - Args: - start_token: The token to start searching from - func: The function to call to test a token for applicability - end_func: The function to call to test a token to determine whether to abort - the search. - distance: The number of tokens to look through before failing search. Must - be positive. If unspecified, will search until the end of the token - chain - reverse: When true, search the tokens before this one instead of the tokens - after it - - Returns: - The first token matching func within distance of this token, or None if no - such token is found. - """ - token = start_token - if reverse: - while token and (distance is None or distance > 0): - previous = token.previous - if previous: - if func(previous): - return previous - if end_func and end_func(previous): - return None - - token = previous - if distance is not None: - distance -= 1 - - else: - while token and (distance is None or distance > 0): - next_token = token.next - if next_token: - if func(next_token): - return next_token - if end_func and end_func(next_token): - return None - - token = next_token - if distance is not None: - distance -= 1 - - return None - - -def Search(start_token, token_types, distance=None, reverse=False): - """Returns the first token of type in token_types within distance. - - Args: - start_token: The token to start searching from - token_types: The allowable types of the token being searched for - distance: The number of tokens to look through before failing search. Must - be positive. If unspecified, will search until the end of the token - chain - reverse: When true, search the tokens before this one instead of the tokens - after it - - Returns: - The first token of any type in token_types within distance of this token, or - None if no such token is found. - """ - return CustomSearch(start_token, lambda token: token.IsAnyType(token_types), - None, distance, reverse) - - -def SearchExcept(start_token, token_types, distance=None, reverse=False): - """Returns the first token not of any type in token_types within distance. - - Args: - start_token: The token to start searching from - token_types: The unallowable types of the token being searched for - distance: The number of tokens to look through before failing search. Must - be positive. If unspecified, will search until the end of the token - chain - reverse: When true, search the tokens before this one instead of the tokens - after it - - Returns: - The first token of any type in token_types within distance of this token, or - None if no such token is found. - """ - return CustomSearch(start_token, - lambda token: not token.IsAnyType(token_types), - None, distance, reverse) - - -def SearchUntil(start_token, token_types, end_types, distance=None, - reverse=False): - """Returns the first token of type in token_types before a token of end_type. - - Args: - start_token: The token to start searching from. - token_types: The allowable types of the token being searched for. - end_types: Types of tokens to abort search if we find. - distance: The number of tokens to look through before failing search. Must - be positive. If unspecified, will search until the end of the token - chain - reverse: When true, search the tokens before this one instead of the tokens - after it - - Returns: - The first token of any type in token_types within distance of this token - before any tokens of type in end_type, or None if no such token is found. - """ - return CustomSearch(start_token, lambda token: token.IsAnyType(token_types), - lambda token: token.IsAnyType(end_types), - distance, reverse) - - -def DeleteToken(token): - """Deletes the given token from the linked list. - - Args: - token: The token to delete - """ - if token.previous: - token.previous.next = token.next - - if token.next: - token.next.previous = token.previous - - following_token = token.next - while following_token and following_token.metadata.last_code == token: - following_token.metadata.last_code = token.metadata.last_code - following_token = following_token.next - - -def DeleteTokens(token, token_count): - """Deletes the given number of tokens starting with the given token. - - Args: - token: The token to start deleting at. - token_count: The total number of tokens to delete. - """ - for i in xrange(1, token_count): - DeleteToken(token.next) - DeleteToken(token) - - -def InsertTokenAfter(new_token, token): - """Insert new_token after token. - - Args: - new_token: A token to be added to the stream - token: A token already in the stream - """ - new_token.previous = token - new_token.next = token.next - - new_token.metadata = copy.copy(token.metadata) - - if token.IsCode(): - new_token.metadata.last_code = token - - if new_token.IsCode(): - following_token = token.next - while following_token and following_token.metadata.last_code == token: - following_token.metadata.last_code = new_token - following_token = following_token.next - - token.next = new_token - if new_token.next: - new_token.next.previous = new_token - - if new_token.start_index is None: - if new_token.line_number == token.line_number: - new_token.start_index = token.start_index + len(token.string) - else: - new_token.start_index = 0 - - iterator = new_token.next - while iterator and iterator.line_number == new_token.line_number: - iterator.start_index += len(new_token.string) - iterator = iterator.next - - -def InsertTokensAfter(new_tokens, token): - """Insert multiple tokens after token. - - Args: - new_tokens: An array of tokens to be added to the stream - token: A token already in the stream - """ - # TODO(user): It would be nicer to have InsertTokenAfter defer to here - # instead of vice-versa. - current_token = token - for new_token in new_tokens: - InsertTokenAfter(new_token, current_token) - current_token = new_token - - -def InsertSpaceTokenAfter(token): - """Inserts a space token after the given token. - - Args: - token: The token to insert a space token after - - Returns: - A single space token - """ - space_token = JavaScriptToken(' ', Type.WHITESPACE, token.line, - token.line_number) - InsertTokenAfter(space_token, token) - - -def InsertBlankLineAfter(token): - """Inserts a blank line after the given token. - - Args: - token: The token to insert a blank line after - - Returns: - A single space token - """ - blank_token = JavaScriptToken('', Type.BLANK_LINE, '', - token.line_number + 1) - InsertLineAfter(token, [blank_token]) - - -def InsertLineAfter(token, new_tokens): - """Inserts a new line consisting of new_tokens after the given token. - - Args: - token: The token to insert after. - new_tokens: The tokens that will make up the new line. - """ - insert_location = token - for new_token in new_tokens: - InsertTokenAfter(new_token, insert_location) - insert_location = new_token - - # Update all subsequent line numbers. - next_token = new_tokens[-1].next - while next_token: - next_token.line_number += 1 - next_token = next_token.next - - -def SplitToken(token, position): - """Splits the token into two tokens at position. - - Args: - token: The token to split - position: The position to split at. Will be the beginning of second token. - - Returns: - The new second token. - """ - new_string = token.string[position:] - token.string = token.string[:position] - - new_token = JavaScriptToken(new_string, token.type, token.line, - token.line_number) - InsertTokenAfter(new_token, token) - - return new_token - - -def Compare(token1, token2): - """Compares two tokens and determines their relative order. - - Args: - token1: The first token to compare. - token2: The second token to compare. - - Returns: - A negative integer, zero, or a positive integer as the first token is - before, equal, or after the second in the token stream. - """ - if token2.line_number != token1.line_number: - return token1.line_number - token2.line_number - else: - return token1.start_index - token2.start_index diff --git a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/setup.py b/src/tools/google_trace_viewer/tracing/third_party/closure_linter/setup.py deleted file mode 100755 index aa2ca4bd..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/closure_linter/setup.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 The Closure Linter Authors. All Rights Reserved. -# -# 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 -# -# 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. - -try: - from setuptools import setup -except ImportError: - from distutils.core import setup - -setup(name='closure_linter', - version='2.3.5', - description='Closure Linter', - license='Apache', - author='The Closure Linter Authors', - author_email='opensource@google.com', - url='http://code.google.com/p/closure-linter', - install_requires=['python-gflags'], - package_dir={'closure_linter': 'closure_linter'}, - packages=['closure_linter', 'closure_linter.common'], - entry_points = { - 'console_scripts': [ - 'gjslint = closure_linter.gjslint:main', - 'fixjsstyle = closure_linter.fixjsstyle:main' - ] - } -) diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/.bower.json b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/.bower.json deleted file mode 100755 index 0a244bdc..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/.bower.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "core-component-page", - "private": true, - "dependencies": { - "webcomponentsjs": "Polymer/webcomponentsjs#^0.5", - "polymer": "Polymer/polymer#^0.5" - }, - "version": "0.5.5", - "homepage": "https://github.com/Polymer/core-component-page", - "_release": "0.5.5", - "_resolution": { - "type": "version", - "tag": "0.5.5", - "commit": "f91588e0297bb3e8e723d4558ab015cf82885571" - }, - "_source": "git://github.com/Polymer/core-component-page.git", - "_target": "^0.5", - "_originalSource": "Polymer/core-component-page" -} \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/README.md b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/README.md deleted file mode 100755 index 7cb18ec7..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/README.md +++ /dev/null @@ -1,6 +0,0 @@ -core-component-page -=================== - -See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-component-page) for more information. - -Note: this is the vulcanized version of [`core-component-page-dev`](https://github.com/Polymer/core-component-page-dev) (the source). diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/bowager-logo.png b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/bowager-logo.png deleted file mode 100755 index 76be9fb0..00000000 Binary files a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/bowager-logo.png and /dev/null differ diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/bower.json b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/bower.json deleted file mode 100755 index 361124c2..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/bower.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "core-component-page", - "private": true, - "dependencies": { - "webcomponentsjs": "Polymer/webcomponentsjs#^0.5", - "polymer": "Polymer/polymer#^0.5" - }, - "version": "0.5.5" -} \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/core-component-page.html b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/core-component-page.html deleted file mode 100755 index 5c642c77..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/core-component-page.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/demo.html b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/demo.html deleted file mode 100755 index 3c414d85..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/demo.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/index.html b/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/index.html deleted file mode 100755 index 294215a7..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/core-component-page/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/.bower.json b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/.bower.json deleted file mode 100755 index 5f5e0c1a..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/.bower.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "polymer", - "description": "Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers.", - "homepage": "http://www.polymer-project.org/", - "keywords": [ - "util", - "client", - "browser", - "web components", - "web-components" - ], - "author": "Polymer Authors ", - "private": true, - "dependencies": { - "core-component-page": "Polymer/core-component-page#^0.5", - "webcomponentsjs": "Polymer/webcomponentsjs#^0.5" - }, - "devDependencies": { - "tools": "Polymer/tools#master", - "web-component-tester": "Polymer/web-component-tester#^1.4.2" - }, - "version": "0.5.5", - "_release": "0.5.5", - "_resolution": { - "type": "version", - "tag": "0.5.5", - "commit": "b94b680c966fc9ea86bc8f14b3af6f13d77f217a" - }, - "_source": "git://github.com/Polymer/polymer.git", - "_target": "~0.5.5", - "_originalSource": "Polymer/polymer" -} \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/README.chromium b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/README.chromium deleted file mode 100755 index 80aa4db6..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/README.chromium +++ /dev/null @@ -1,16 +0,0 @@ -me: polymer -Short Name: polymer -URL: http://www.polymer-project.org/ -Version: 0.5.5 -Revision: None -Date: Mar 24, 2015 -License: BSD -License File: NOT_SHIPPED -Security Critical: no - -Description: -Polymer framework. - -Local modifications: - - Removed comment lines with {{var_names}} from polymer.js because of - breaking GRIT in Chromium. See #854 diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/README.md b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/README.md deleted file mode 100755 index 2c03674f..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Polymer - -[![Polymer build status](http://www.polymer-project.org/build/polymer-dev/status.png "Polymer build status")](http://build.chromium.org/p/client.polymer/waterfall) - -## Brief Overview - -For more detailed info goto [http://polymer-project.org/](http://polymer-project.org/). - -Polymer is a new type of library for the web, designed to leverage the existing browser infrastructure to provide the encapsulation and extendability currently only available in JS libraries. - -Polymer is based on a set of future technologies, including [Shadow DOM](http://w3c.github.io/webcomponents/spec/shadow/), [Custom Elements](http://w3c.github.io/webcomponents/spec/custom/) and Model Driven Views. Currently these technologies are implemented as polyfills or shims, but as browsers adopt these features natively, the platform code that drives Polymer evacipates, leaving only the value-adds. - -## Tools & Testing - -For running tests or building minified files, consult the [tooling information](https://www.polymer-project.org/resources/tooling-strategy.html). - -## Releases - -[Release (tagged) versions](https://github.com/Polymer/polymer/releases) of Polymer include concatenated and minified sources for your convenience. - -[![Analytics](https://ga-beacon.appspot.com/UA-39334307-2/Polymer/polymer/README)](https://github.com/igrigorik/ga-beacon) diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/bower.json b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/bower.json deleted file mode 100755 index dbc75960..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/bower.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "polymer", - "description": "Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers.", - "homepage": "http://www.polymer-project.org/", - "keywords": [ - "util", - "client", - "browser", - "web components", - "web-components" - ], - "author": "Polymer Authors ", - "private": true, - "dependencies": { - "core-component-page": "Polymer/core-component-page#^0.5", - "webcomponentsjs": "Polymer/webcomponentsjs#^0.5" - }, - "devDependencies": { - "tools": "Polymer/tools#master", - "web-component-tester": "Polymer/web-component-tester#^1.4.2" - }, - "version": "0.5.5" -} \ No newline at end of file diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/layout.html b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/layout.html deleted file mode 100755 index b22caddd..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/layout.html +++ /dev/null @@ -1,286 +0,0 @@ - - diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/polymer.html b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/polymer.html deleted file mode 100755 index 7e3d8f1e..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/polymer.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - diff --git a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/polymer.js b/src/tools/google_trace_viewer/tracing/third_party/components/polymer/polymer.js deleted file mode 100755 index 67c2306e..00000000 --- a/src/tools/google_trace_viewer/tracing/third_party/components/polymer/polymer.js +++ /dev/null @@ -1,11857 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ -// @version 0.5.5 -window.PolymerGestures = {}; - -(function(scope) { - var hasFullPath = false; - - // test for full event path support - var pathTest = document.createElement('meta'); - if (pathTest.createShadowRoot) { - var sr = pathTest.createShadowRoot(); - var s = document.createElement('span'); - sr.appendChild(s); - pathTest.addEventListener('testpath', function(ev) { - if (ev.path) { - // if the span is in the event path, then path[0] is the real source for all events - hasFullPath = ev.path[0] === s; - } - ev.stopPropagation(); - }); - var ev = new CustomEvent('testpath', {bubbles: true}); - // must add node to DOM to trigger event listener - document.head.appendChild(pathTest); - s.dispatchEvent(ev); - pathTest.parentNode.removeChild(pathTest); - sr = s = null; - } - pathTest = null; - - var target = { - shadow: function(inEl) { - if (inEl) { - return inEl.shadowRoot || inEl.webkitShadowRoot; - } - }, - canTarget: function(shadow) { - return shadow && Boolean(shadow.elementFromPoint); - }, - targetingShadow: function(inEl) { - var s = this.shadow(inEl); - if (this.canTarget(s)) { - return s; - } - }, - olderShadow: function(shadow) { - var os = shadow.olderShadowRoot; - if (!os) { - var se = shadow.querySelector('shadow'); - if (se) { - os = se.olderShadowRoot; - } - } - return os; - }, - allShadows: function(element) { - var shadows = [], s = this.shadow(element); - while(s) { - shadows.push(s); - s = this.olderShadow(s); - } - return shadows; - }, - searchRoot: function(inRoot, x, y) { - var t, st, sr, os; - if (inRoot) { - t = inRoot.elementFromPoint(x, y); - if (t) { - // found element, check if it has a ShadowRoot - sr = this.targetingShadow(t); - } else if (inRoot !== document) { - // check for sibling roots - sr = this.olderShadow(inRoot); - } - // search other roots, fall back to light dom element - return this.searchRoot(sr, x, y) || t; - } - }, - owner: function(element) { - if (!element) { - return document; - } - var s = element; - // walk up until you hit the shadow root or document - while (s.parentNode) { - s = s.parentNode; - } - // the owner element is expected to be a Document or ShadowRoot - if (s.nodeType != Node.DOCUMENT_NODE && s.nodeType != Node.DOCUMENT_FRAGMENT_NODE) { - s = document; - } - return s; - }, - findTarget: function(inEvent) { - if (hasFullPath && inEvent.path && inEvent.path.length) { - return inEvent.path[0]; - } - var x = inEvent.clientX, y = inEvent.clientY; - // if the listener is in the shadow root, it is much faster to start there - var s = this.owner(inEvent.target); - // if x, y is not in this root, fall back to document search - if (!s.elementFromPoint(x, y)) { - s = document; - } - return this.searchRoot(s, x, y); - }, - findTouchAction: function(inEvent) { - var n; - if (hasFullPath && inEvent.path && inEvent.path.length) { - var path = inEvent.path; - for (var i = 0; i < path.length; i++) { - n = path[i]; - if (n.nodeType === Node.ELEMENT_NODE && n.hasAttribute('touch-action')) { - return n.getAttribute('touch-action'); - } - } - } else { - n = inEvent.target; - while(n) { - if (n.nodeType === Node.ELEMENT_NODE && n.hasAttribute('touch-action')) { - return n.getAttribute('touch-action'); - } - n = n.parentNode || n.host; - } - } - // auto is default - return "auto"; - }, - LCA: function(a, b) { - if (a === b) { - return a; - } - if (a && !b) { - return a; - } - if (b && !a) { - return b; - } - if (!b && !a) { - return document; - } - // fast case, a is a direct descendant of b or vice versa - if (a.contains && a.contains(b)) { - return a; - } - if (b.contains && b.contains(a)) { - return b; - } - var adepth = this.depth(a); - var bdepth = this.depth(b); - var d = adepth - bdepth; - if (d >= 0) { - a = this.walk(a, d); - } else { - b = this.walk(b, -d); - } - while (a && b && a !== b) { - a = a.parentNode || a.host; - b = b.parentNode || b.host; - } - return a; - }, - walk: function(n, u) { - for (var i = 0; n && (i < u); i++) { - n = n.parentNode || n.host; - } - return n; - }, - depth: function(n) { - var d = 0; - while(n) { - d++; - n = n.parentNode || n.host; - } - return d; - }, - deepContains: function(a, b) { - var common = this.LCA(a, b); - // if a is the common ancestor, it must "deeply" contain b - return common === a; - }, - insideNode: function(node, x, y) { - var rect = node.getBoundingClientRect(); - return (rect.left <= x) && (x <= rect.right) && (rect.top <= y) && (y <= rect.bottom); - }, - path: function(event) { - var p; - if (hasFullPath && event.path && event.path.length) { - p = event.path; - } else { - p = []; - var n = this.findTarget(event); - while (n) { - p.push(n); - n = n.parentNode || n.host; - } - } - return p; - } - }; - scope.targetFinding = target; - /** - * Given an event, finds the "deepest" node that could have been the original target before ShadowDOM retargetting - * - * @param {Event} Event An event object with clientX and clientY properties - * @return {Element} The probable event origninator - */ - scope.findTarget = target.findTarget.bind(target); - /** - * Determines if the "container" node deeply contains the "containee" node, including situations where the "containee" is contained by one or more ShadowDOM - * roots. - * - * @param {Node} container - * @param {Node} containee - * @return {Boolean} - */ - scope.deepContains = target.deepContains.bind(target); - - /** - * Determines if the x/y position is inside the given node. - * - * Example: - * - * function upHandler(event) { - * var innode = PolymerGestures.insideNode(event.target, event.clientX, event.clientY); - * if (innode) { - * // wait for tap? - * } else { - * // tap will never happen - * } - * } - * - * @param {Node} node - * @param {Number} x Screen X position - * @param {Number} y screen Y position - * @return {Boolean} - */ - scope.insideNode = target.insideNode; - -})(window.PolymerGestures); - -(function() { - function shadowSelector(v) { - return 'html /deep/ ' + selector(v); - } - function selector(v) { - return '[touch-action="' + v + '"]'; - } - function rule(v) { - return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + ';}'; - } - var attrib2css = [ - 'none', - 'auto', - 'pan-x', - 'pan-y', - { - rule: 'pan-x pan-y', - selectors: [ - 'pan-x pan-y', - 'pan-y pan-x' - ] - }, - 'manipulation' - ]; - var styles = ''; - // only install stylesheet if the browser has touch action support - var hasTouchAction = typeof document.head.style.touchAction === 'string'; - // only add shadow selectors if shadowdom is supported - var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoot; - - if (hasTouchAction) { - attrib2css.forEach(function(r) { - if (String(r) === r) { - styles += selector(r) + rule(r) + '\n'; - if (hasShadowRoot) { - styles += shadowSelector(r) + rule(r) + '\n'; - } - } else { - styles += r.selectors.map(selector) + rule(r.rule) + '\n'; - if (hasShadowRoot) { - styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n'; - } - } - }); - - var el = document.createElement('style'); - el.textContent = styles; - document.head.appendChild(el); - } -})(); - -/** - * This is the constructor for new PointerEvents. - * - * New Pointer Events must be given a type, and an optional dictionary of - * initialization properties. - * - * Due to certain platform requirements, events returned from the constructor - * identify as MouseEvents. - * - * @constructor - * @param {String} inType The type of the event to create. - * @param {Object} [inDict] An optional dictionary of initial event properties. - * @return {Event} A new PointerEvent of type `inType` and initialized with properties from `inDict`. - */ -(function(scope) { - - var MOUSE_PROPS = [ - 'bubbles', - 'cancelable', - 'view', - 'detail', - 'screenX', - 'screenY', - 'clientX', - 'clientY', - 'ctrlKey', - 'altKey', - 'shiftKey', - 'metaKey', - 'button', - 'relatedTarget', - 'pageX', - 'pageY' - ]; - - var MOUSE_DEFAULTS = [ - false, - false, - null, - null, - 0, - 0, - 0, - 0, - false, - false, - false, - false, - 0, - null, - 0, - 0 - ]; - - var NOP_FACTORY = function(){ return function(){}; }; - - var eventFactory = { - // TODO(dfreedm): this is overridden by tap recognizer, needs review - preventTap: NOP_FACTORY, - makeBaseEvent: function(inType, inDict) { - var e = document.createEvent('Event'); - e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false); - e.preventTap = eventFactory.preventTap(e); - return e; - }, - makeGestureEvent: function(inType, inDict) { - inDict = inDict || Object.create(null); - - var e = this.makeBaseEvent(inType, inDict); - for (var i = 0, keys = Object.keys(inDict), k; i < keys.length; i++) { - k = keys[i]; - if( k !== 'bubbles' && k !== 'cancelable' ) { - e[k] = inDict[k]; - } - } - return e; - }, - makePointerEvent: function(inType, inDict) { - inDict = inDict || Object.create(null); - - var e = this.makeBaseEvent(inType, inDict); - // define inherited MouseEvent properties - for(var i = 2, p; i < MOUSE_PROPS.length; i++) { - p = MOUSE_PROPS[i]; - e[p] = inDict[p] || MOUSE_DEFAULTS[i]; - } - e.buttons = inDict.buttons || 0; - - // Spec requires that pointers without pressure specified use 0.5 for down - // state and 0 for up state. - var pressure = 0; - if (inDict.pressure) { - pressure = inDict.pressure; - } else { - pressure = e.buttons ? 0.5 : 0; - } - - // add x/y properties aliased to clientX/Y - e.x = e.clientX; - e.y = e.clientY; - - // define the properties of the PointerEvent interface - e.pointerId = inDict.pointerId || 0; - e.width = inDict.width || 0; - e.height = inDict.height || 0; - e.pressure = pressure; - e.tiltX = inDict.tiltX || 0; - e.tiltY = inDict.tiltY || 0; - e.pointerType = inDict.pointerType || ''; - e.hwTimestamp = inDict.hwTimestamp || 0; - e.isPrimary = inDict.isPrimary || false; - e._source = inDict._source || ''; - return e; - } - }; - - scope.eventFactory = eventFactory; -})(window.PolymerGestures); - -/** - * This module implements an map of pointer states - */ -(function(scope) { - var USE_MAP = window.Map && window.Map.prototype.forEach; - var POINTERS_FN = function(){ return this.size; }; - function PointerMap() { - if (USE_MAP) { - var m = new Map(); - m.pointers = POINTERS_FN; - return m; - } else { - this.keys = []; - this.values = []; - } - } - - PointerMap.prototype = { - set: function(inId, inEvent) { - var i = this.keys.indexOf(inId); - if (i > -1) { - this.values[i] = inEvent; - } else { - this.keys.push(inId); - this.values.push(inEvent); - } - }, - has: function(inId) { - return this.keys.indexOf(inId) > -1; - }, - 'delete': function(inId) { - var i = this.keys.indexOf(inId); - if (i > -1) { - this.keys.splice(i, 1); - this.values.splice(i, 1); - } - }, - get: function(inId) { - var i = this.keys.indexOf(inId); - return this.values[i]; - }, - clear: function() { - this.keys.length = 0; - this.values.length = 0; - }, - // return value, key, map - forEach: function(callback, thisArg) { - this.values.forEach(function(v, i) { - callback.call(thisArg, v, this.keys[i], this); - }, this); - }, - pointers: function() { - return this.keys.length; - } - }; - - scope.PointerMap = PointerMap; -})(window.PolymerGestures); - -(function(scope) { - var CLONE_PROPS = [ - // MouseEvent - 'bubbles', - 'cancelable', - 'view', - 'detail', - 'screenX', - 'screenY', - 'clientX', - 'clientY', - 'ctrlKey', - 'altKey', - 'shiftKey', - 'metaKey', - 'button', - 'relatedTarget', - // DOM Level 3 - 'buttons', - // PointerEvent - 'pointerId', - 'width', - 'height', - 'pressure', - 'tiltX', - 'tiltY', - 'pointerType', - 'hwTimestamp', - 'isPrimary', - // event instance - 'type', - 'target', - 'currentTarget', - 'which', - 'pageX', - 'pageY', - 'timeStamp', - // gesture addons - 'preventTap', - 'tapPrevented', - '_source' - ]; - - var CLONE_DEFAULTS = [ - // MouseEvent - false, - false, - null, - null, - 0, - 0, - 0, - 0, - false, - false, - false, - false, - 0, - null, - // DOM Level 3 - 0, - // PointerEvent - 0, - 0, - 0, - 0, - 0, - 0, - '', - 0, - false, - // event instance - '', - null, - null, - 0, - 0, - 0, - 0, - function(){}, - false - ]; - - var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined'); - - var eventFactory = scope.eventFactory; - - // set of recognizers to run for the currently handled event - var currentGestures; - - /** - * This module is for normalizing events. Mouse and Touch events will be - * collected here, and fire PointerEvents that have the same semantics, no - * matter the source. - * Events fired: - * - pointerdown: a pointing is added - * - pointerup: a pointer is removed - * - pointermove: a pointer is moved - * - pointerover: a pointer crosses into an element - * - pointerout: a pointer leaves an element - * - pointercancel: a pointer will no longer generate events - */ - var dispatcher = { - IS_IOS: false, - pointermap: new scope.PointerMap(), - requiredGestures: new scope.PointerMap(), - eventMap: Object.create(null), - // Scope objects for native events. - // This exists for ease of testing. - eventSources: Object.create(null), - eventSourceList: [], - gestures: [], - // map gesture event -> {listeners: int, index: gestures[int]} - dependencyMap: { - // make sure down and up are in the map to trigger "register" - down: {listeners: 0, index: -1}, - up: {listeners: 0, index: -1} - }, - gestureQueue: [], - /** - * Add a new event source that will generate pointer events. - * - * `inSource` must contain an array of event names named `events`, and - * functions with the names specified in the `events` array. - * @param {string} name A name for the event source - * @param {Object} source A new source of platform events. - */ - registerSource: function(name, source) { - var s = source; - var newEvents = s.events; - if (newEvents) { - newEvents.forEach(function(e) { - if (s[e]) { - this.eventMap[e] = s[e].bind(s); - } - }, this); - this.eventSources[name] = s; - this.eventSourceList.push(s); - } - }, - registerGesture: function(name, source) { - var obj = Object.create(null); - obj.listeners = 0; - obj.index = this.gestures.length; - for (var i = 0, g; i < source.exposes.length; i++) { - g = source.exposes[i].toLowerCase(); - this.dependencyMap[g] = obj; - } - this.gestures.push(source); - }, - register: function(element, initial) { - var l = this.eventSourceList.length; - for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) { - // call eventsource register - es.register.call(es, element, initial); - } - }, - unregister: function(element) { - var l = this.eventSourceList.length; - for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) { - // call eventsource register - es.unregister.call(es, element); - } - }, - // EVENTS - down: function(inEvent) { - this.requiredGestures.set(inEvent.pointerId, currentGestures); - this.fireEvent('down', inEvent); - }, - move: function(inEvent) { - // pipe move events into gesture queue directly - inEvent.type = 'move'; - this.fillGestureQueue(inEvent); - }, - up: function(inEvent) { - this.fireEvent('up', inEvent); - this.requiredGestures.delete(inEvent.pointerId); - }, - cancel: function(inEvent) { - inEvent.tapPrevented = true; - this.fireEvent('up', inEvent); - this.requiredGestures.delete(inEvent.pointerId); - }, - addGestureDependency: function(node, currentGestures) { - var gesturesWanted = node._pgEvents; - if (gesturesWanted && currentGestures) { - var gk = Object.keys(gesturesWanted); - for (var i = 0, r, ri, g; i < gk.length; i++) { - // gesture - g = gk[i]; - if (gesturesWanted[g] > 0) { - // lookup gesture recognizer - r = this.dependencyMap[g]; - // recognizer index - ri = r ? r.index : -1; - currentGestures[ri] = true; - } - } - } - }, - // LISTENER LOGIC - eventHandler: function(inEvent) { - // This is used to prevent multiple dispatch of events from - // platform events. This can happen when two elements in different scopes - // are set up to create pointer events, which is relevant to Shadow DOM. - - var type = inEvent.type; - - // only generate the list of desired events on "down" - if (type === 'touchstart' || type === 'mousedown' || type === 'pointerdown' || type === 'MSPointerDown') { - if (!inEvent._handledByPG) { - currentGestures = {}; - } - - // in IOS mode, there is only a listener on the document, so this is not re-entrant - if (this.IS_IOS) { - var ev = inEvent; - if (type === 'touchstart') { - var ct = inEvent.changedTouches[0]; - // set up a fake event to give to the path builder - ev = {target: inEvent.target, clientX: ct.clientX, clientY: ct.clientY, path: inEvent.path}; - } - // use event path if available, otherwise build a path from target finding - var nodes = inEvent.path || scope.targetFinding.path(ev); - for (var i = 0, n; i < nodes.length; i++) { - n = nodes[i]; - this.addGestureDependency(n, currentGestures); - } - } else { - this.addGestureDependency(inEvent.currentTarget, currentGestures); - } - } - - if (inEvent._handledByPG) { - return; - } - var fn = this.eventMap && this.eventMap[type]; - if (fn) { - fn(inEvent); - } - inEvent._handledByPG = true; - }, - // set up event listeners - listen: function(target, events) { - for (var i = 0, l = events.length, e; (i < l) && (e = events[i]); i++) { - this.addEvent(target, e); - } - }, - // remove event listeners - unlisten: function(target, events) { - for (var i = 0, l = events.length, e; (i < l) && (e = events[i]); i++) { - this.removeEvent(target, e); - } - }, - addEvent: function(target, eventName) { - target.addEventListener(eventName, this.boundHandler); - }, - removeEvent: function(target, eventName) { - target.removeEventListener(eventName, this.boundHandler); - }, - // EVENT CREATION AND TRACKING - /** - * Creates a new Event of type `inType`, based on the information in - * `inEvent`. - * - * @param {string} inType A string representing the type of event to create - * @param {Event} inEvent A platform event with a target - * @return {Event} A PointerEvent of type `inType` - */ - makeEvent: function(inType, inEvent) { - var e = eventFactory.makePointerEvent(inType, inEvent); - e.preventDefault = inEvent.preventDefault; - e.tapPrevented = inEvent.tapPrevented; - e._target = e._target || inEvent.target; - return e; - }, - // make and dispatch an event in one call - fireEvent: function(inType, inEvent) { - var e = this.makeEvent(inType, inEvent); - return this.dispatchEvent(e); - }, - /** - * Returns a snapshot of inEvent, with writable properties. - * - * @param {Event} inEvent An event that contains properties to copy. - * @return {Object} An object containing shallow copies of `inEvent`'s - * properties. - */ - cloneEvent: function(inEvent) { - var eventCopy = Object.create(null), p; - for (var i = 0; i < CLONE_PROPS.length; i++) { - p = CLONE_PROPS[i]; - eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i]; - // Work around SVGInstanceElement shadow tree - // Return the element that is represented by the instance for Safari, Chrome, IE. - // This is the behavior implemented by Firefox. - if (p === 'target' || p === 'relatedTarget') { - if (HAS_SVG_INSTANCE && eventCopy[p] instanceof SVGElementInstance) { - eventCopy[p] = eventCopy[p].correspondingUseElement; - } - } - } - // keep the semantics of preventDefault - eventCopy.preventDefault = function() { - inEvent.preventDefault(); - }; - return eventCopy; - }, - /** - * Dispatches the event to its target. - * - * @param {Event} inEvent The event to be dispatched. - * @return {Boolean} True if an event handler returns true, false otherwise. - */ - dispatchEvent: function(inEvent) { - var t = inEvent._target; - if (t) { - t.dispatchEvent(inEvent); - // clone the event for the gesture system to process - // clone after dispatch to pick up gesture prevention code - var clone = this.cloneEvent(inEvent); - clone.target = t; - this.fillGestureQueue(clone); - } - }, - gestureTrigger: function() { - // process the gesture queue - for (var i = 0, e, rg; i < this.gestureQueue.length; i++) { - e = this.gestureQueue[i]; - rg = e._requiredGestures; - if (rg) { - for (var j = 0, g, fn; j < this.gestures.length; j++) { - // only run recognizer if an element in the source event's path is listening for those gestures - if (rg[j]) { - g = this.gestures[j]; - fn = g[e.type]; - if (fn) { - fn.call(g, e); - } - } - } - } - } - this.gestureQueue.length = 0; - }, - fillGestureQueue: function(ev) { - // only trigger the gesture queue once - if (!this.gestureQueue.length) { - requestAnimationFrame(this.boundGestureTrigger); - } - ev._requiredGestures = this.requiredGestures.get(ev.pointerId); - this.gestureQueue.push(ev); - } - }; - dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); - dispatcher.boundGestureTrigger = dispatcher.gestureTrigger.bind(dispatcher); - scope.dispatcher = dispatcher; - - /** - * Listen for `gesture` on `node` with the `handler` function - * - * If `handler` is the first listener for `gesture`, the underlying gesture recognizer is then enabled. - * - * @param {Element} node - * @param {string} gesture - * @return Boolean `gesture` is a valid gesture - */ - scope.activateGesture = function(node, gesture) { - var g = gesture.toLowerCase(); - var dep = dispatcher.dependencyMap[g]; - if (dep) { - var recognizer = dispatcher.gestures[dep.index]; - if (!node._pgListeners) { - dispatcher.register(node); - node._pgListeners = 0; - } - // TODO(dfreedm): re-evaluate bookkeeping to avoid using attributes - if (recognizer) { - var touchAction = recognizer.defaultActions && recognizer.defaultActions[g]; - var actionNode; - switch(node.nodeType) { - case Node.ELEMENT_NODE: - actionNode = node; - break; - case Node.DOCUMENT_FRAGMENT_NODE: - actionNode = node.host; - break; - default: - actionNode = null; - break; - } - if (touchAction && actionNode && !actionNode.hasAttribute('touch-action')) { - actionNode.setAttribute('touch-action', touchAction); - } - } - if (!node._pgEvents) { - node._pgEvents = {}; - } - node._pgEvents[g] = (node._pgEvents[g] || 0) + 1; - node._pgListeners++; - } - return Boolean(dep); - }; - - /** - * - * Listen for `gesture` from `node` with `handler` function. - * - * @param {Element} node - * @param {string} gesture - * @param {Function} handler - * @param {Boolean} capture - */ - scope.addEventListener = function(node, gesture, handler, capture) { - if (handler) { - scope.activateGesture(node, gesture); - node.addEventListener(gesture, handler, capture); - } - }; - - /** - * Tears down the gesture configuration for `node` - * - * If `handler` is the last listener for `gesture`, the underlying gesture recognizer is disabled. - * - * @param {Element} node - * @param {string} gesture - * @return Boolean `gesture` is a valid gesture - */ - scope.deactivateGesture = function(node, gesture) { - var g = gesture.toLowerCase(); - var dep = dispatcher.dependencyMap[g]; - if (dep) { - if (node._pgListeners > 0) { - node._pgListeners--; - } - if (node._pgListeners === 0) { - dispatcher.unregister(node); - } - if (node._pgEvents) { - if (node._pgEvents[g] > 0) { - node._pgEvents[g]--; - } else { - node._pgEvents[g] = 0; - } - } - } - return Boolean(dep); - }; - - /** - * Stop listening for `gesture` from `node` with `handler` function. - * - * @param {Element} node - * @param {string} gesture - * @param {Function} handler - * @param {Boolean} capture - */ - scope.removeEventListener = function(node, gesture, handler, capture) { - if (handler) { - scope.deactivateGesture(node, gesture); - node.removeEventListener(gesture, handler, capture); - } - }; -})(window.PolymerGestures); - -(function(scope) { - var dispatcher = scope.dispatcher; - var pointermap = dispatcher.pointermap; - // radius around touchend that swallows mouse events - var DEDUP_DIST = 25; - - var WHICH_TO_BUTTONS = [0, 1, 4, 2]; - - var currentButtons = 0; - - var FIREFOX_LINUX = /Linux.*Firefox\//i; - - var HAS_BUTTONS = (function() { - // firefox on linux returns spec-incorrect values for mouseup.buttons - // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.buttons#See_also - // https://codereview.chromium.org/727593003/#msg16 - if (FIREFOX_LINUX.test(navigator.userAgent)) { - return false; - } - try { - return new MouseEvent('test', {buttons: 1}).buttons === 1; - } catch (e) { - return false; - } - })(); - - // handler block for native mouse events - var mouseEvents = { - POINTER_ID: 1, - POINTER_TYPE: 'mouse', - events: [ - 'mousedown', - 'mousemove', - 'mouseup' - ], - exposes: [ - 'down', - 'up', - 'move' - ], - register: function(target) { - dispatcher.listen(target, this.events); - }, - unregister: function(target) { - if (target.nodeType === Node.DOCUMENT_NODE) { - return; - } - dispatcher.unlisten(target, this.events); - }, - lastTouches: [], - // collide with the global mouse listener - isEventSimulatedFromTouch: function(inEvent) { - var lts = this.lastTouches; - var x = inEvent.clientX, y = inEvent.clientY; - for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) { - // simulated mouse events will be swallowed near a primary touchend - var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); - if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) { - return true; - } - } - }, - prepareEvent: function(inEvent) { - var e = dispatcher.cloneEvent(inEvent); - e.pointerId = this.POINTER_ID; - e.isPrimary = true; - e.pointerType = this.POINTER_TYPE; - e._source = 'mouse'; - if (!HAS_BUTTONS) { - var type = inEvent.type; - var bit = WHICH_TO_BUTTONS[inEvent.which] || 0; - if (type === 'mousedown') { - currentButtons |= bit; - } else if (type === 'mouseup') { - currentButtons &= ~bit; - } - e.buttons = currentButtons; - } - return e; - }, - mousedown: function(inEvent) { - if (!this.isEventSimulatedFromTouch(inEvent)) { - var p = pointermap.has(this.POINTER_ID); - var e = this.prepareEvent(inEvent); - e.target = scope.findTarget(inEvent); - pointermap.set(this.POINTER_ID, e.target); - dispatcher.down(e); - } - }, - mousemove: function(inEvent) { - if (!this.isEventSimulatedFromTouch(inEvent)) { - var target = pointermap.get(this.POINTER_ID); - if (target) { - var e = this.prepareEvent(inEvent); - e.target = target; - // handle case where we missed a mouseup - if ((HAS_BUTTONS ? e.buttons : e.which) === 0) { - if (!HAS_BUTTONS) { - currentButtons = e.buttons = 0; - } - dispatcher.cancel(e); - this.cleanupMouse(e.buttons); - } else { - dispatcher.move(e); - } - } - } - }, - mouseup: function(inEvent) { - if (!this.isEventSimulatedFromTouch(inEvent)) { - var e = this.prepareEvent(inEvent); - e.relatedTarget = scope.findTarget(inEvent); - e.target = pointermap.get(this.POINTER_ID); - dispatcher.up(e); - this.cleanupMouse(e.buttons); - } - }, - cleanupMouse: function(buttons) { - if (buttons === 0) { - pointermap.delete(this.POINTER_ID); - } - } - }; - - scope.mouseEvents = mouseEvents; -})(window.PolymerGestures); - -(function(scope) { - var dispatcher = scope.dispatcher; - var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding); - var pointermap = dispatcher.pointermap; - var touchMap = Array.prototype.map.call.bind(Array.prototype.map); - // This should be long enough to ignore compat mouse events made by touch - var DEDUP_TIMEOUT = 2500; - var DEDUP_DIST = 25; - var CLICK_COUNT_TIMEOUT = 200; - var HYSTERESIS = 20; - var ATTRIB = 'touch-action'; - // TODO(dfreedm): disable until http://crbug.com/399765 is resolved - // var HAS_TOUCH_ACTION = ATTRIB in document.head.style; - var HAS_TOUCH_ACTION = false; - - // handler block for native touch events - var touchEvents = { - IS_IOS: false, - events: [ - 'touchstart', - 'touchmove', - 'touchend', - 'touchcancel' - ], - exposes: [ - 'down', - 'up', - 'move' - ], - register: function(target, initial) { - if (this.IS_IOS ? initial : !initial) { - dispatcher.listen(target, this.events); - } - }, - unregister: function(target) { - if (!this.IS_IOS) { - dispatcher.unlisten(target, this.events); - } - }, - scrollTypes: { - EMITTER: 'none', - XSCROLLER: 'pan-x', - YSCROLLER: 'pan-y', - }, - touchActionToScrollType: function(touchAction) { - var t = touchAction; - var st = this.scrollTypes; - if (t === st.EMITTER) { - return 'none'; - } else if (t === st.XSCROLLER) { - return 'X'; - } else if (t === st.YSCROLLER) { - return 'Y'; - } else { - return 'XY'; - } - }, - POINTER_TYPE: 'touch', - firstTouch: null, - isPrimaryTouch: function(inTouch) { - return this.firstTouch === inTouch.identifier; - }, - setPrimaryTouch: function(inTouch) { - // set primary touch if there no pointers, or the only pointer is the mouse - if (pointermap.pointers() === 0 || (pointermap.pointers() === 1 && pointermap.has(1))) { - this.firstTouch = inTouch.identifier; - this.firstXY = {X: inTouch.clientX, Y: inTouch.clientY}; - this.firstTarget = inTouch.target; - this.scrolling = null; - this.cancelResetClickCount(); - } - }, - removePrimaryPointer: function(inPointer) { - if (inPointer.isPrimary) { - this.firstTouch = null; - this.firstXY = null; - this.resetClickCount(); - } - }, - clickCount: 0, - resetId: null, - resetClickCount: function() { - var fn = function() { - this.clickCount = 0; - this.resetId = null; - }.bind(this); - this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT); - }, - cancelResetClickCount: function() { - if (this.resetId) { - clearTimeout(this.resetId); - } - }, - typeToButtons: function(type) { - var ret = 0; - if (type === 'touchstart' || type === 'touchmove') { - ret = 1; - } - return ret; - }, - findTarget: function(touch, id) { - if (this.currentTouchEvent.type === 'touchstart') { - if (this.isPrimaryTouch(touch)) { - var fastPath = { - clientX: touch.clientX, - clientY: touch.clientY, - path: this.currentTouchEvent.path, - target: this.currentTouchEvent.target - }; - return scope.findTarget(fastPath); - } else { - return scope.findTarget(touch); - } - } - // reuse target we found in touchstart - return pointermap.get(id); - }, - touchToPointer: function(inTouch) { - var cte = this.currentTouchEvent; - var e = dispatcher.cloneEvent(inTouch); - // Spec specifies that pointerId 1 is reserved for Mouse. - // Touch identifiers can start at 0. - // Add 2 to the touch identifier for compatibility. - var id = e.pointerId = inTouch.identifier + 2; - e.target = this.findTarget(inTouch, id); - e.bubbles = true; - e.cancelable = true; - e.detail = this.clickCount; - e.buttons = this.typeToButtons(cte.type); - e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; - e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; - e.pressure = inTouch.webkitForce || inTouch.force || 0.5; - e.isPrimary = this.isPrimaryTouch(inTouch); - e.pointerType = this.POINTER_TYPE; - e._source = 'touch'; - // forward touch preventDefaults - var self = this; - e.preventDefault = function() { - self.scrolling = false; - self.firstXY = null; - cte.preventDefault(); - }; - return e; - }, - processTouches: function(inEvent, inFunction) { - var tl = inEvent.changedTouches; - this.currentTouchEvent = inEvent; - for (var i = 0, t, p; i < tl.length; i++) { - t = tl[i]; - p = this.touchToPointer(t); - if (inEvent.type === 'touchstart') { - pointermap.set(p.pointerId, p.target); - } - if (pointermap.has(p.pointerId)) { - inFunction.call(this, p); - } - if (inEvent.type === 'touchend' || inEvent._cancel) { - this.cleanUpPointer(p); - } - } - }, - // For single axis scrollers, determines whether the element should emit - // pointer events or behave as a scroller - shouldScroll: function(inEvent) { - if (this.firstXY) { - var ret; - var touchAction = scope.targetFinding.findTouchAction(inEvent); - var scrollAxis = this.touchActionToScrollType(touchAction); - if (scrollAxis === 'none') { - // this element is a touch-action: none, should never scroll - ret = false; - } else if (scrollAxis === 'XY') { - // this element should always scroll - ret = true; - } else { - var t = inEvent.changedTouches[0]; - // check the intended scroll axis, and other axis - var a = scrollAxis; - var oa = scrollAxis === 'Y' ? 'X' : 'Y'; - var da = Math.abs(t['client' + a] - this.firstXY[a]); - var doa = Math.abs(t['client' + oa] - this.firstXY[oa]); - // if delta in the scroll axis > delta other axis, scroll instead of - // making events - ret = da >= doa; - } - return ret; - } - }, - findTouch: function(inTL, inId) { - for (var i = 0, l = inTL.length, t; i < l && (t = inTL[i]); i++) { - if (t.identifier === inId) { - return true; - } - } - }, - // In some instances, a touchstart can happen without a touchend. This - // leaves the pointermap in a broken state. - // Therefore, on every touchstart, we remove the touches that did not fire a - // touchend event. - // To keep state globally consistent, we fire a - // pointercancel for this "abandoned" touch - vacuumTouches: function(inEvent) { - var tl = inEvent.touches; - // pointermap.pointers() should be < tl.length here, as the touchstart has not - // been processed yet. - if (pointermap.pointers() >= tl.length) { - var d = []; - pointermap.forEach(function(value, key) { - // Never remove pointerId == 1, which is mouse. - // Touch identifiers are 2 smaller than their pointerId, which is the - // index in pointermap. - if (key !== 1 && !this.findTouch(tl, key - 2)) { - var p = value; - d.push(p); - } - }, this); - d.forEach(function(p) { - this.cancel(p); - pointermap.delete(p.pointerId); - }, this); - } - }, - touchstart: function(inEvent) { - this.vacuumTouches(inEvent); - this.setPrimaryTouch(inEvent.changedTouches[0]); - this.dedupSynthMouse(inEvent); - if (!this.scrolling) { - this.clickCount++; - this.processTouches(inEvent, this.down); - } - }, - down: function(inPointer) { - dispatcher.down(inPointer); - }, - touchmove: function(inEvent) { - if (HAS_TOUCH_ACTION) { - // touchevent.cancelable == false is sent when the page is scrolling under native Touch Action in Chrome 36 - // https://groups.google.com/a/chromium.org/d/msg/input-dev/wHnyukcYBcA/b9kmtwM1jJQJ - if (inEvent.cancelable) { - this.processTouches(inEvent, this.move); - } - } else { - if (!this.scrolling) { - if (this.scrolling === null && this.shouldScroll(inEvent)) { - this.scrolling = true; - } else { - this.scrolling = false; - inEvent.preventDefault(); - this.processTouches(inEvent, this.move); - } - } else if (this.firstXY) { - var t = inEvent.changedTouches[0]; - var dx = t.clientX - this.firstXY.X; - var dy = t.clientY - this.firstXY.Y; - var dd = Math.sqrt(dx * dx + dy * dy); - if (dd >= HYSTERESIS) { - this.touchcancel(inEvent); - this.scrolling = true; - this.firstXY = null; - } - } - } - }, - move: function(inPointer) { - dispatcher.move(inPointer); - }, - touchend: function(inEvent) { - this.dedupSynthMouse(inEvent); - this.processTouches(inEvent, this.up); - }, - up: function(inPointer) { - inPointer.relatedTarget = scope.findTarget(inPointer); - dispatcher.up(inPointer); - }, - cancel: function(inPointer) { - dispatcher.cancel(inPointer); - }, - touchcancel: function(inEvent) { - inEvent._cancel = true; - this.processTouches(inEvent, this.cancel); - }, - cleanUpPointer: function(inPointer) { - pointermap['delete'](inPointer.pointerId); - this.removePrimaryPointer(inPointer); - }, - // prevent synth mouse events from creating pointer events - dedupSynthMouse: function(inEvent) { - var lts = scope.mouseEvents.lastTouches; - var t = inEvent.changedTouches[0]; - // only the primary finger will synth mouse events - if (this.isPrimaryTouch(t)) { - // remember x/y of last touch - var lt = {x: t.clientX, y: t.clientY}; - lts.push(lt); - var fn = (function(lts, lt){ - var i = lts.indexOf(lt); - if (i > -1) { - lts.splice(i, 1); - } - }).bind(null, lts, lt); - setTimeout(fn, DEDUP_TIMEOUT); - } - } - }; - - // prevent "ghost clicks" that come from elements that were removed in a touch handler - var STOP_PROP_FN = Event.prototype.stopImmediatePropagation || Event.prototype.stopPropagation; - document.addEventListener('click', function(ev) { - var x = ev.clientX, y = ev.clientY; - // check if a click is within DEDUP_DIST px radius of the touchstart - var closeTo = function(touch) { - var dx = Math.abs(x - touch.x), dy = Math.abs(y - touch.y); - return (dx <= DEDUP_DIST && dy <= DEDUP_DIST); - }; - // if click coordinates are close to touch coordinates, assume the click came from a touch - var wasTouched = scope.mouseEvents.lastTouches.some(closeTo); - // if the click came from touch, and the touchstart target is not in the path of the click event, - // then the touchstart target was probably removed, and the click should be "busted" - var path = scope.targetFinding.path(ev); - if (wasTouched) { - for (var i = 0; i < path.length; i++) { - if (path[i] === touchEvents.firstTarget) { - return; - } - } - ev.preventDefault(); - STOP_PROP_FN.call(ev); - } - }, true); - - scope.touchEvents = touchEvents; -})(window.PolymerGestures); - -(function(scope) { - var dispatcher = scope.dispatcher; - var pointermap = dispatcher.pointermap; - var HAS_BITMAP_TYPE = window.MSPointerEvent && typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE === 'number'; - var msEvents = { - events: [ - 'MSPointerDown', - 'MSPointerMove', - 'MSPointerUp', - 'MSPointerCancel', - ], - register: function(target) { - dispatcher.listen(target, this.events); - }, - unregister: function(target) { - if (target.nodeType === Node.DOCUMENT_NODE) { - return; - } - dispatcher.unlisten(target, this.events); - }, - POINTER_TYPES: [ - '', - 'unavailable', - 'touch', - 'pen', - 'mouse' - ], - prepareEvent: function(inEvent) { - var e = inEvent; - e = dispatcher.cloneEvent(inEvent); - if (HAS_BITMAP_TYPE) { - e.pointerType = this.POINTER_TYPES[inEvent.pointerType]; - } - e._source = 'ms'; - return e; - }, - cleanup: function(id) { - pointermap['delete'](id); - }, - MSPointerDown: function(inEvent) { - var e = this.prepareEvent(inEvent); - e.target = scope.findTarget(inEvent); - pointermap.set(inEvent.pointerId, e.target); - dispatcher.down(e); - }, - MSPointerMove: function(inEvent) { - var target = pointermap.get(inEvent.pointerId); - if (target) { - var e = this.prepareEvent(inEvent); - e.target = target; - dispatcher.move(e); - } - }, - MSPointerUp: function(inEvent) { - var e = this.prepareEvent(inEvent); - e.relatedTarget = scope.findTarget(inEvent); - e.target = pointermap.get(e.pointerId); - dispatcher.up(e); - this.cleanup(inEvent.pointerId); - }, - MSPointerCancel: function(inEvent) { - var e = this.prepareEvent(inEvent); - e.relatedTarget = scope.findTarget(inEvent); - e.target = pointermap.get(e.pointerId); - dispatcher.cancel(e); - this.cleanup(inEvent.pointerId); - } - }; - - scope.msEvents = msEvents; -})(window.PolymerGestures); - -(function(scope) { - var dispatcher = scope.dispatcher; - var pointermap = dispatcher.pointermap; - var pointerEvents = { - events: [ - 'pointerdown', - 'pointermove', - 'pointerup', - 'pointercancel' - ], - prepareEvent: function(inEvent) { - var e = dispatcher.cloneEvent(inEvent); - e._source = 'pointer'; - return e; - }, - register: function(target) { - dispatcher.listen(target, this.events); - }, - unregister: function(target) { - if (target.nodeType === Node.DOCUMENT_NODE) { - return; - } - dispatcher.unlisten(target, this.events); - }, - cleanup: function(id) { - pointermap['delete'](id); - }, - pointerdown: function(inEvent) { - var e = this.prepareEvent(inEvent); - e.target = scope.findTarget(inEvent); - pointermap.set(e.pointerId, e.target); - dispatcher.down(e); - }, - pointermove: function(inEvent) { - var target = pointermap.get(inEvent.pointerId); - if (target) { - var e = this.prepareEvent(inEvent); - e.target = target; - dispatcher.move(e); - } - }, - pointerup: function(inEvent) { - var e = this.prepareEvent(inEvent); - e.relatedTarget = scope.findTarget(inEvent); - e.target = pointermap.get(e.pointerId); - dispatcher.up(e); - this.cleanup(inEvent.pointerId); - }, - pointercancel: function(inEvent) { - var e = this.prepareEvent(inEvent); - e.relatedTarget = scope.findTarget(inEvent); - e.target = pointermap.get(e.pointerId); - dispatcher.cancel(e); - this.cleanup(inEvent.pointerId); - } - }; - - scope.pointerEvents = pointerEvents; -})(window.PolymerGestures); - -/** - * This module contains the handlers for native platform events. - * From here, the dispatcher is called to create unified pointer events. - * Included are touch events (v1), mouse events, and MSPointerEvents. - */ -(function(scope) { - - var dispatcher = scope.dispatcher; - var nav = window.navigator; - - if (window.PointerEvent) { - dispatcher.registerSource('pointer', scope.pointerEvents); - } else if (nav.msPointerEnabled) { - dispatcher.registerSource('ms', scope.msEvents); - } else { - dispatcher.registerSource('mouse', scope.mouseEvents); - if (window.ontouchstart !== undefined) { - dispatcher.registerSource('touch', scope.touchEvents); - } - } - - // Work around iOS bugs https://bugs.webkit.org/show_bug.cgi?id=135628 and https://bugs.webkit.org/show_bug.cgi?id=136506 - var ua = navigator.userAgent; - var IS_IOS = ua.match(/iPad|iPhone|iPod/) && 'ontouchstart' in window; - - dispatcher.IS_IOS = IS_IOS; - scope.touchEvents.IS_IOS = IS_IOS; - - dispatcher.register(document, true); -})(window.PolymerGestures); - -/** - * This event denotes the beginning of a series of tracking events. - * - * @module PointerGestures - * @submodule Events - * @class trackstart - */ -/** - * Pixels moved in the x direction since trackstart. - * @type Number - * @property dx - */ -/** - * Pixes moved in the y direction since trackstart. - * @type Number - * @property dy - */ -/** - * Pixels moved in the x direction since the last track. - * @type Number - * @property ddx - */ -/** - * Pixles moved in the y direction since the last track. - * @type Number - * @property ddy - */ -/** - * The clientX position of the track gesture. - * @type Number - * @property clientX - */ -/** - * The clientY position of the track gesture. - * @type Number - * @property clientY - */ -/** - * The pageX position of the track gesture. - * @type Number - * @property pageX - */ -/** - * The pageY position of the track gesture. - * @type Number - * @property pageY - */ -/** - * The screenX position of the track gesture. - * @type Number - * @property screenX - */ -/** - * The screenY position of the track gesture. - * @type Number - * @property screenY - */ -/** - * The last x axis direction of the pointer. - * @type Number - * @property xDirection - */ -/** - * The last y axis direction of the pointer. - * @type Number - * @property yDirection - */ -/** - * A shared object between all tracking events. - * @type Object - * @property trackInfo - */ -/** - * The element currently under the pointer. - * @type Element - * @property relatedTarget - */ -/** - * The type of pointer that make the track gesture. - * @type String - * @property pointerType - */ -/** - * - * This event fires for all pointer movement being tracked. - * - * @class track - * @extends trackstart - */ -/** - * This event fires when the pointer is no longer being tracked. - * - * @class trackend - * @extends trackstart - */ - - (function(scope) { - var dispatcher = scope.dispatcher; - var eventFactory = scope.eventFactory; - var pointermap = new scope.PointerMap(); - var track = { - events: [ - 'down', - 'move', - 'up', - ], - exposes: [ - 'trackstart', - 'track', - 'trackx', - 'tracky', - 'trackend' - ], - defaultActions: { - 'track': 'none', - 'trackx': 'pan-y', - 'tracky': 'pan-x' - }, - WIGGLE_THRESHOLD: 4, - clampDir: function(inDelta) { - return inDelta > 0 ? 1 : -1; - }, - calcPositionDelta: function(inA, inB) { - var x = 0, y = 0; - if (inA && inB) { - x = inB.pageX - inA.pageX; - y = inB.pageY - inA.pageY; - } - return {x: x, y: y}; - }, - fireTrack: function(inType, inEvent, inTrackingData) { - var t = inTrackingData; - var d = this.calcPositionDelta(t.downEvent, inEvent); - var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent); - if (dd.x) { - t.xDirection = this.clampDir(dd.x); - } else if (inType === 'trackx') { - return; - } - if (dd.y) { - t.yDirection = this.clampDir(dd.y); - } else if (inType === 'tracky') { - return; - } - var gestureProto = { - bubbles: true, - cancelable: true, - trackInfo: t.trackInfo, - relatedTarget: inEvent.relatedTarget, - pointerType: inEvent.pointerType, - pointerId: inEvent.pointerId, - _source: 'track' - }; - if (inType !== 'tracky') { - gestureProto.x = inEvent.x; - gestureProto.dx = d.x; - gestureProto.ddx = dd.x; - gestureProto.clientX = inEvent.clientX; - gestureProto.pageX = inEvent.pageX; - gestureProto.screenX = inEvent.screenX; - gestureProto.xDirection = t.xDirection; - } - if (inType !== 'trackx') { - gestureProto.dy = d.y; - gestureProto.ddy = dd.y; - gestureProto.y = inEvent.y; - gestureProto.clientY = inEvent.clientY; - gestureProto.pageY = inEvent.pageY; - gestureProto.screenY = inEvent.screenY; - gestureProto.yDirection = t.yDirection; - } - var e = eventFactory.makeGestureEvent(inType, gestureProto); - t.downTarget.dispatchEvent(e); - }, - down: function(inEvent) { - if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.buttons === 1 : true)) { - var p = { - downEvent: inEvent, - downTarget: inEvent.target, - trackInfo: {}, - lastMoveEvent: null, - xDirection: 0, - yDirection: 0, - tracking: false - }; - pointermap.set(inEvent.pointerId, p); - } - }, - move: function(inEvent) { - var p = pointermap.get(inEvent.pointerId); - if (p) { - if (!p.tracking) { - var d = this.calcPositionDelta(p.downEvent, inEvent); - var move = d.x * d.x + d.y * d.y; - // start tracking only if finger moves more than WIGGLE_THRESHOLD - if (move > this.WIGGLE_THRESHOLD) { - p.tracking = true; - p.lastMoveEvent = p.downEvent; - this.fireTrack('trackstart', inEvent, p); - } - } - if (p.tracking) { - this.fireTrack('track', inEvent, p); - this.fireTrack('trackx', inEvent, p); - this.fireTrack('tracky', inEvent, p); - } - p.lastMoveEvent = inEvent; - } - }, - up: function(inEvent) { - var p = pointermap.get(inEvent.pointerId); - if (p) { - if (p.tracking) { - this.fireTrack('trackend', inEvent, p); - } - pointermap.delete(inEvent.pointerId); - } - } - }; - dispatcher.registerGesture('track', track); - })(window.PolymerGestures); - -/** - * This event is fired when a pointer is held down for 200ms. - * - * @module PointerGestures - * @submodule Events - * @class hold - */ -/** - * Type of pointer that made the holding event. - * @type String - * @property pointerType - */ -/** - * Screen X axis position of the held pointer - * @type Number - * @property clientX - */ -/** - * Screen Y axis position of the held pointer - * @type Number - * @property clientY - */ -/** - * Type of pointer that made the holding event. - * @type String - * @property pointerType - */ -/** - * This event is fired every 200ms while a pointer is held down. - * - * @class holdpulse - * @extends hold - */ -/** - * Milliseconds pointer has been held down. - * @type Number - * @property holdTime - */ -/** - * This event is fired when a held pointer is released or moved. - * - * @class release - */ - -(function(scope) { - var dispatcher = scope.dispatcher; - var eventFactory = scope.eventFactory; - var hold = { - // wait at least HOLD_DELAY ms between hold and pulse events - HOLD_DELAY: 200, - // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold - WIGGLE_THRESHOLD: 16, - events: [ - 'down', - 'move', - 'up', - ], - exposes: [ - 'hold', - 'holdpulse', - 'release' - ], - heldPointer: null, - holdJob: null, - pulse: function() { - var hold = Date.now() - this.heldPointer.timeStamp; - var type = this.held ? 'holdpulse' : 'hold'; - this.fireHold(type, hold); - this.held = true; - }, - cancel: function() { - clearInterval(this.holdJob); - if (this.held) { - this.fireHold('release'); - } - this.held = false; - this.heldPointer = null; - this.target = null; - this.holdJob = null; - }, - down: function(inEvent) { - if (inEvent.isPrimary && !this.heldPointer) { - this.heldPointer = inEvent; - this.target = inEvent.target; - this.holdJob = setInterval(this.pulse.bind(this), this.HOLD_DELAY); - } - }, - up: function(inEvent) { - if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) { - this.cancel(); - } - }, - move: function(inEvent) { - if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) { - var x = inEvent.clientX - this.heldPointer.clientX; - var y = inEvent.clientY - this.heldPointer.clientY; - if ((x * x + y * y) > this.WIGGLE_THRESHOLD) { - this.cancel(); - } - } - }, - fireHold: function(inType, inHoldTime) { - var p = { - bubbles: true, - cancelable: true, - pointerType: this.heldPointer.pointerType, - pointerId: this.heldPointer.pointerId, - x: this.heldPointer.clientX, - y: this.heldPointer.clientY, - _source: 'hold' - }; - if (inHoldTime) { - p.holdTime = inHoldTime; - } - var e = eventFactory.makeGestureEvent(inType, p); - this.target.dispatchEvent(e); - } - }; - dispatcher.registerGesture('hold', hold); -})(window.PolymerGestures); - -/** - * This event is fired when a pointer quickly goes down and up, and is used to - * denote activation. - * - * Any gesture event can prevent the tap event from being created by calling - * `event.preventTap`. - * - * Any pointer event can prevent the tap by setting the `tapPrevented` property - * on itself. - * - * @module PointerGestures - * @submodule Events - * @class tap - */ -/** - * X axis position of the tap. - * @property x - * @type Number - */ -/** - * Y axis position of the tap. - * @property y - * @type Number - */ -/** - * Type of the pointer that made the tap. - * @property pointerType - * @type String - */ -(function(scope) { - var dispatcher = scope.dispatcher; - var eventFactory = scope.eventFactory; - var pointermap = new scope.PointerMap(); - var tap = { - events: [ - 'down', - 'up' - ], - exposes: [ - 'tap' - ], - down: function(inEvent) { - if (inEvent.isPrimary && !inEvent.tapPrevented) { - pointermap.set(inEvent.pointerId, { - target: inEvent.target, - buttons: inEvent.buttons, - x: inEvent.clientX, - y: inEvent.clientY - }); - } - }, - shouldTap: function(e, downState) { - var tap = true; - if (e.pointerType === 'mouse') { - // only allow left click to tap for mouse - tap = (e.buttons ^ 1) && (downState.buttons & 1); - } - return tap && !e.tapPrevented; - }, - up: function(inEvent) { - var start = pointermap.get(inEvent.pointerId); - if (start && this.shouldTap(inEvent, start)) { - // up.relatedTarget is target currently under finger - var t = scope.targetFinding.LCA(start.target, inEvent.relatedTarget); - if (t) { - var e = eventFactory.makeGestureEvent('tap', { - bubbles: true, - cancelable: true, - x: inEvent.clientX, - y: inEvent.clientY, - detail: inEvent.detail, - pointerType: inEvent.pointerType, - pointerId: inEvent.pointerId, - altKey: inEvent.altKey, - ctrlKey: inEvent.ctrlKey, - metaKey: inEvent.metaKey, - shiftKey: inEvent.shiftKey, - _source: 'tap' - }); - t.dispatchEvent(e); - } - } - pointermap.delete(inEvent.pointerId); - } - }; - // patch eventFactory to remove id from tap's pointermap for preventTap calls - eventFactory.preventTap = function(e) { - return function() { - e.tapPrevented = true; - pointermap.delete(e.pointerId); - }; - }; - dispatcher.registerGesture('tap', tap); -})(window.PolymerGestures); - -/* - * Basic strategy: find the farthest apart points, use as diameter of circle - * react to size change and rotation of the chord - */ - -/** - * @module pointer-gestures - * @submodule Events - * @class pinch - */ -/** - * Scale of the pinch zoom gesture - * @property scale - * @type Number - */ -/** - * Center X position of pointers causing pinch - * @property centerX - * @type Number - */ -/** - * Center Y position of pointers causing pinch - * @property centerY - * @type Number - */ - -/** - * @module pointer-gestures - * @submodule Events - * @class rotate - */ -/** - * Angle (in degrees) of rotation. Measured from starting positions of pointers. - * @property angle - * @type Number - */ -/** - * Center X position of pointers causing rotation - * @property centerX - * @type Number - */ -/** - * Center Y position of pointers causing rotation - * @property centerY - * @type Number - */ -(function(scope) { - var dispatcher = scope.dispatcher; - var eventFactory = scope.eventFactory; - var pointermap = new scope.PointerMap(); - var RAD_TO_DEG = 180 / Math.PI; - var pinch = { - events: [ - 'down', - 'up', - 'move', - 'cancel' - ], - exposes: [ - 'pinchstart', - 'pinch', - 'pinchend', - 'rotate' - ], - defaultActions: { - 'pinch': 'none', - 'rotate': 'none' - }, - reference: {}, - down: function(inEvent) { - pointermap.set(inEvent.pointerId, inEvent); - if (pointermap.pointers() == 2) { - var points = this.calcChord(); - var angle = this.calcAngle(points); - this.reference = { - angle: angle, - diameter: points.diameter, - target: scope.targetFinding.LCA(points.a.target, points.b.target) - }; - - this.firePinch('pinchstart', points.diameter, points); - } - }, - up: function(inEvent) { - var p = pointermap.get(inEvent.pointerId); - var num = pointermap.pointers(); - if (p) { - if (num === 2) { - // fire 'pinchend' before deleting pointer - var points = this.calcChord(); - this.firePinch('pinchend', points.diameter, points); - } - pointermap.delete(inEvent.pointerId); - } - }, - move: function(inEvent) { - if (pointermap.has(inEvent.pointerId)) { - pointermap.set(inEvent.pointerId, inEvent); - if (pointermap.pointers() > 1) { - this.calcPinchRotate(); - } - } - }, - cancel: function(inEvent) { - this.up(inEvent); - }, - firePinch: function(type, diameter, points) { - var zoom = diameter / this.reference.diameter; - var e = eventFactory.makeGestureEvent(type, { - bubbles: true, - cancelable: true, - scale: zoom, - centerX: points.center.x, - centerY: points.center.y, - _source: 'pinch' - }); - this.reference.target.dispatchEvent(e); - }, - fireRotate: function(angle, points) { - var diff = Math.round((angle - this.reference.angle) % 360); - var e = eventFactory.makeGestureEvent('rotate', { - bubbles: true, - cancelable: true, - angle: diff, - centerX: points.center.x, - centerY: points.center.y, - _source: 'pinch' - }); - this.reference.target.dispatchEvent(e); - }, - calcPinchRotate: function() { - var points = this.calcChord(); - var diameter = points.diameter; - var angle = this.calcAngle(points); - if (diameter != this.reference.diameter) { - this.firePinch('pinch', diameter, points); - } - if (angle != this.reference.angle) { - this.fireRotate(angle, points); - } - }, - calcChord: function() { - var pointers = []; - pointermap.forEach(function(p) { - pointers.push(p); - }); - var dist = 0; - // start with at least two pointers - var points = {a: pointers[0], b: pointers[1]}; - var x, y, d; - for (var i = 0; i < pointers.length; i++) { - var a = pointers[i]; - for (var j = i + 1; j < pointers.length; j++) { - var b = pointers[j]; - x = Math.abs(a.clientX - b.clientX); - y = Math.abs(a.clientY - b.clientY); - d = x + y; - if (d > dist) { - dist = d; - points = {a: a, b: b}; - } - } - } - x = Math.abs(points.a.clientX + points.b.clientX) / 2; - y = Math.abs(points.a.clientY + points.b.clientY) / 2; - points.center = { x: x, y: y }; - points.diameter = dist; - return points; - }, - calcAngle: function(points) { - var x = points.a.clientX - points.b.clientX; - var y = points.a.clientY - points.b.clientY; - return (360 + Math.atan2(y, x) * RAD_TO_DEG) % 360; - } - }; - dispatcher.registerGesture('pinch', pinch); -})(window.PolymerGestures); - -(function (global) { - 'use strict'; - - var Token, - TokenName, - Syntax, - Messages, - source, - index, - length, - delegate, - lookahead, - state; - - Token = { - BooleanLiteral: 1, - EOF: 2, - Identifier: 3, - Keyword: 4, - NullLiteral: 5, - NumericLiteral: 6, - Punctuator: 7, - StringLiteral: 8 - }; - - TokenName = {}; - TokenName[Token.BooleanLiteral] = 'Boolean'; - TokenName[Token.EOF] = ''; - TokenName[Token.Identifier] = 'Identifier'; - TokenName[Token.Keyword] = 'Keyword'; - TokenName[Token.NullLiteral] = 'Null'; - TokenName[Token.NumericLiteral] = 'Numeric'; - TokenName[Token.Punctuator] = 'Punctuator'; - TokenName[Token.StringLiteral] = 'String'; - - Syntax = { - ArrayExpression: 'ArrayExpression', - BinaryExpression: 'BinaryExpression', - CallExpression: 'CallExpression', - ConditionalExpression: 'ConditionalExpression', - EmptyStatement: 'EmptyStatement', - ExpressionStatement: 'ExpressionStatement', - Identifier: 'Identifier', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - ObjectExpression: 'ObjectExpression', - Program: 'Program', - Property: 'Property', - ThisExpression: 'ThisExpression', - UnaryExpression: 'UnaryExpression' - }; - - // Error messages should be identical to V8. - Messages = { - UnexpectedToken: 'Unexpected token %0', - UnknownLabel: 'Undefined label \'%0\'', - Redeclaration: '%0 \'%1\' has already been declared' - }; - - // Ensure the condition is true, otherwise throw an error. - // This is only to have a better contract semantic, i.e. another safety net - // to catch a logic error. The condition shall be fulfilled in normal case. - // Do NOT use this to enforce a certain condition on any user input. - - function assert(condition, message) { - if (!condition) { - throw new Error('ASSERT: ' + message); - } - } - - function isDecimalDigit(ch) { - return (ch >= 48 && ch <= 57); // 0..9 - } - - - // 7.2 White Space - - function isWhiteSpace(ch) { - return (ch === 32) || // space - (ch === 9) || // tab - (ch === 0xB) || - (ch === 0xC) || - (ch === 0xA0) || - (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); - } - - // 7.3 Line Terminators - - function isLineTerminator(ch) { - return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); - } - - // 7.6 Identifier Names and Identifiers - - function isIdentifierStart(ch) { - return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) - (ch >= 65 && ch <= 90) || // A..Z - (ch >= 97 && ch <= 122); // a..z - } - - function isIdentifierPart(ch) { - return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) - (ch >= 65 && ch <= 90) || // A..Z - (ch >= 97 && ch <= 122) || // a..z - (ch >= 48 && ch <= 57); // 0..9 - } - - // 7.6.1.1 Keywords - - function isKeyword(id) { - return (id === 'this') - } - - // 7.4 Comments - - function skipWhitespace() { - while (index < length && isWhiteSpace(source.charCodeAt(index))) { - ++index; - } - } - - function getIdentifier() { - var start, ch; - - start = index++; - while (index < length) { - ch = source.charCodeAt(index); - if (isIdentifierPart(ch)) { - ++index; - } else { - break; - } - } - - return source.slice(start, index); - } - - function scanIdentifier() { - var start, id, type; - - start = index; - - id = getIdentifier(); - - // There is no keyword or literal with only one character. - // Thus, it must be an identifier. - if (id.length === 1) { - type = Token.Identifier; - } else if (isKeyword(id)) { - type = Token.Keyword; - } else if (id === 'null') { - type = Token.NullLiteral; - } else if (id === 'true' || id === 'false') { - type = Token.BooleanLiteral; - } else { - type = Token.Identifier; - } - - return { - type: type, - value: id, - range: [start, index] - }; - } - - - // 7.7 Punctuators - - function scanPunctuator() { - var start = index, - code = source.charCodeAt(index), - code2, - ch1 = source[index], - ch2; - - switch (code) { - - // Check for most common single-character punctuators. - case 46: // . dot - case 40: // ( open bracket - case 41: // ) close bracket - case 59: // ; semicolon - case 44: // , comma - case 123: // { open curly brace - case 125: // } close curly brace - case 91: // [ - case 93: // ] - case 58: // : - case 63: // ? - ++index; - return { - type: Token.Punctuator, - value: String.fromCharCode(code), - range: [start, index] - }; - - default: - code2 = source.charCodeAt(index + 1); - - // '=' (char #61) marks an assignment or comparison operator. - if (code2 === 61) { - switch (code) { - case 37: // % - case 38: // & - case 42: // *: - case 43: // + - case 45: // - - case 47: // / - case 60: // < - case 62: // > - case 124: // | - index += 2; - return { - type: Token.Punctuator, - value: String.fromCharCode(code) + String.fromCharCode(code2), - range: [start, index] - }; - - case 33: // ! - case 61: // = - index += 2; - - // !== and === - if (source.charCodeAt(index) === 61) { - ++index; - } - return { - type: Token.Punctuator, - value: source.slice(start, index), - range: [start, index] - }; - default: - break; - } - } - break; - } - - // Peek more characters. - - ch2 = source[index + 1]; - - // Other 2-character punctuators: && || - - if (ch1 === ch2 && ('&|'.indexOf(ch1) >= 0)) { - index += 2; - return { - type: Token.Punctuator, - value: ch1 + ch2, - range: [start, index] - }; - } - - if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { - ++index; - return { - type: Token.Punctuator, - value: ch1, - range: [start, index] - }; - } - - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - // 7.8.3 Numeric Literals - function scanNumericLiteral() { - var number, start, ch; - - ch = source[index]; - assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), - 'Numeric literal must start with a decimal digit or a decimal point'); - - start = index; - number = ''; - if (ch !== '.') { - number = source[index++]; - ch = source[index]; - - // Hex number starts with '0x'. - // Octal number starts with '0'. - if (number === '0') { - // decimal number starts with '0' such as '09' is illegal. - if (ch && isDecimalDigit(ch.charCodeAt(0))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - while (isDecimalDigit(source.charCodeAt(index))) { - number += source[index++]; - } - ch = source[index]; - } - - if (ch === '.') { - number += source[index++]; - while (isDecimalDigit(source.charCodeAt(index))) { - number += source[index++]; - } - ch = source[index]; - } - - if (ch === 'e' || ch === 'E') { - number += source[index++]; - - ch = source[index]; - if (ch === '+' || ch === '-') { - number += source[index++]; - } - if (isDecimalDigit(source.charCodeAt(index))) { - while (isDecimalDigit(source.charCodeAt(index))) { - number += source[index++]; - } - } else { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - if (isIdentifierStart(source.charCodeAt(index))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - return { - type: Token.NumericLiteral, - value: parseFloat(number), - range: [start, index] - }; - } - - // 7.8.4 String Literals - - function scanStringLiteral() { - var str = '', quote, start, ch, octal = false; - - quote = source[index]; - assert((quote === '\'' || quote === '"'), - 'String literal must starts with a quote'); - - start = index; - ++index; - - while (index < length) { - ch = source[index++]; - - if (ch === quote) { - quote = ''; - break; - } else if (ch === '\\') { - ch = source[index++]; - if (!ch || !isLineTerminator(ch.charCodeAt(0))) { - switch (ch) { - case 'n': - str += '\n'; - break; - case 'r': - str += '\r'; - break; - case 't': - str += '\t'; - break; - case 'b': - str += '\b'; - break; - case 'f': - str += '\f'; - break; - case 'v': - str += '\x0B'; - break; - - default: - str += ch; - break; - } - } else { - if (ch === '\r' && source[index] === '\n') { - ++index; - } - } - } else if (isLineTerminator(ch.charCodeAt(0))) { - break; - } else { - str += ch; - } - } - - if (quote !== '') { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - return { - type: Token.StringLiteral, - value: str, - octal: octal, - range: [start, index] - }; - } - - function isIdentifierName(token) { - return token.type === Token.Identifier || - token.type === Token.Keyword || - token.type === Token.BooleanLiteral || - token.type === Token.NullLiteral; - } - - function advance() { - var ch; - - skipWhitespace(); - - if (index >= length) { - return { - type: Token.EOF, - range: [index, index] - }; - } - - ch = source.charCodeAt(index); - - // Very common: ( and ) and ; - if (ch === 40 || ch === 41 || ch === 58) { - return scanPunctuator(); - } - - // String literal starts with single quote (#39) or double quote (#34). - if (ch === 39 || ch === 34) { - return scanStringLiteral(); - } - - if (isIdentifierStart(ch)) { - return scanIdentifier(); - } - - // Dot (.) char #46 can also start a floating-point number, hence the need - // to check the next character. - if (ch === 46) { - if (isDecimalDigit(source.charCodeAt(index + 1))) { - return scanNumericLiteral(); - } - return scanPunctuator(); - } - - if (isDecimalDigit(ch)) { - return scanNumericLiteral(); - } - - return scanPunctuator(); - } - - function lex() { - var token; - - token = lookahead; - index = token.range[1]; - - lookahead = advance(); - - index = token.range[1]; - - return token; - } - - function peek() { - var pos; - - pos = index; - lookahead = advance(); - index = pos; - } - - // Throw an exception - - function throwError(token, messageFormat) { - var error, - args = Array.prototype.slice.call(arguments, 2), - msg = messageFormat.replace( - /%(\d)/g, - function (whole, index) { - assert(index < args.length, 'Message reference must be in range'); - return args[index]; - } - ); - - error = new Error(msg); - error.index = index; - error.description = msg; - throw error; - } - - // Throw an exception because of the token. - - function throwUnexpected(token) { - throwError(token, Messages.UnexpectedToken, token.value); - } - - // Expect the next token to match the specified punctuator. - // If not, an exception will be thrown. - - function expect(value) { - var token = lex(); - if (token.type !== Token.Punctuator || token.value !== value) { - throwUnexpected(token); - } - } - - // Return true if the next token matches the specified punctuator. - - function match(value) { - return lookahead.type === Token.Punctuator && lookahead.value === value; - } - - // Return true if the next token matches the specified keyword - - function matchKeyword(keyword) { - return lookahead.type === Token.Keyword && lookahead.value === keyword; - } - - function consumeSemicolon() { - // Catch the very common case first: immediately a semicolon (char #59). - if (source.charCodeAt(index) === 59) { - lex(); - return; - } - - skipWhitespace(); - - if (match(';')) { - lex(); - return; - } - - if (lookahead.type !== Token.EOF && !match('}')) { - throwUnexpected(lookahead); - } - } - - // 11.1.4 Array Initialiser - - function parseArrayInitialiser() { - var elements = []; - - expect('['); - - while (!match(']')) { - if (match(',')) { - lex(); - elements.push(null); - } else { - elements.push(parseExpression()); - - if (!match(']')) { - expect(','); - } - } - } - - expect(']'); - - return delegate.createArrayExpression(elements); - } - - // 11.1.5 Object Initialiser - - function parseObjectPropertyKey() { - var token; - - skipWhitespace(); - token = lex(); - - // Note: This function is called only from parseObjectProperty(), where - // EOF and Punctuator tokens are already filtered out. - if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { - return delegate.createLiteral(token); - } - - return delegate.createIdentifier(token.value); - } - - function parseObjectProperty() { - var token, key; - - token = lookahead; - skipWhitespace(); - - if (token.type === Token.EOF || token.type === Token.Punctuator) { - throwUnexpected(token); - } - - key = parseObjectPropertyKey(); - expect(':'); - return delegate.createProperty('init', key, parseExpression()); - } - - function parseObjectInitialiser() { - var properties = []; - - expect('{'); - - while (!match('}')) { - properties.push(parseObjectProperty()); - - if (!match('}')) { - expect(','); - } - } - - expect('}'); - - return delegate.createObjectExpression(properties); - } - - // 11.1.6 The Grouping Operator - - function parseGroupExpression() { - var expr; - - expect('('); - - expr = parseExpression(); - - expect(')'); - - return expr; - } - - - // 11.1 Primary Expressions - - function parsePrimaryExpression() { - var type, token, expr; - - if (match('(')) { - return parseGroupExpression(); - } - - type = lookahead.type; - - if (type === Token.Identifier) { - expr = delegate.createIdentifier(lex().value); - } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { - expr = delegate.createLiteral(lex()); - } else if (type === Token.Keyword) { - if (matchKeyword('this')) { - lex(); - expr = delegate.createThisExpression(); - } - } else if (type === Token.BooleanLiteral) { - token = lex(); - token.value = (token.value === 'true'); - expr = delegate.createLiteral(token); - } else if (type === Token.NullLiteral) { - token = lex(); - token.value = null; - expr = delegate.createLiteral(token); - } else if (match('[')) { - expr = parseArrayInitialiser(); - } else if (match('{')) { - expr = parseObjectInitialiser(); - } - - if (expr) { - return expr; - } - - throwUnexpected(lex()); - } - - // 11.2 Left-Hand-Side Expressions - - function parseArguments() { - var args = []; - - expect('('); - - if (!match(')')) { - while (index < length) { - args.push(parseExpression()); - if (match(')')) { - break; - } - expect(','); - } - } - - expect(')'); - - return args; - } - - function parseNonComputedProperty() { - var token; - - token = lex(); - - if (!isIdentifierName(token)) { - throwUnexpected(token); - } - - return delegate.createIdentifier(token.value); - } - - function parseNonComputedMember() { - expect('.'); - - return parseNonComputedProperty(); - } - - function parseComputedMember() { - var expr; - - expect('['); - - expr = parseExpression(); - - expect(']'); - - return expr; - } - - function parseLeftHandSideExpression() { - var expr, args, property; - - expr = parsePrimaryExpression(); - - while (true) { - if (match('[')) { - property = parseComputedMember(); - expr = delegate.createMemberExpression('[', expr, property); - } else if (match('.')) { - property = parseNonComputedMember(); - expr = delegate.createMemberExpression('.', expr, property); - } else if (match('(')) { - args = parseArguments(); - expr = delegate.createCallExpression(expr, args); - } else { - break; - } - } - - return expr; - } - - // 11.3 Postfix Expressions - - var parsePostfixExpression = parseLeftHandSideExpression; - - // 11.4 Unary Operators - - function parseUnaryExpression() { - var token, expr; - - if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { - expr = parsePostfixExpression(); - } else if (match('+') || match('-') || match('!')) { - token = lex(); - expr = parseUnaryExpression(); - expr = delegate.createUnaryExpression(token.value, expr); - } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { - throwError({}, Messages.UnexpectedToken); - } else { - expr = parsePostfixExpression(); - } - - return expr; - } - - function binaryPrecedence(token) { - var prec = 0; - - if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { - return 0; - } - - switch (token.value) { - case '||': - prec = 1; - break; - - case '&&': - prec = 2; - break; - - case '==': - case '!=': - case '===': - case '!==': - prec = 6; - break; - - case '<': - case '>': - case '<=': - case '>=': - case 'instanceof': - prec = 7; - break; - - case 'in': - prec = 7; - break; - - case '+': - case '-': - prec = 9; - break; - - case '*': - case '/': - case '%': - prec = 11; - break; - - default: - break; - } - - return prec; - } - - // 11.5 Multiplicative Operators - // 11.6 Additive Operators - // 11.7 Bitwise Shift Operators - // 11.8 Relational Operators - // 11.9 Equality Operators - // 11.10 Binary Bitwise Operators - // 11.11 Binary Logical Operators - - function parseBinaryExpression() { - var expr, token, prec, stack, right, operator, left, i; - - left = parseUnaryExpression(); - - token = lookahead; - prec = binaryPrecedence(token); - if (prec === 0) { - return left; - } - token.prec = prec; - lex(); - - right = parseUnaryExpression(); - - stack = [left, token, right]; - - while ((prec = binaryPrecedence(lookahead)) > 0) { - - // Reduce: make a binary expression from the three topmost entries. - while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { - right = stack.pop(); - operator = stack.pop().value; - left = stack.pop(); - expr = delegate.createBinaryExpression(operator, left, right); - stack.push(expr); - } - - // Shift. - token = lex(); - token.prec = prec; - stack.push(token); - expr = parseUnaryExpression(); - stack.push(expr); - } - - // Final reduce to clean-up the stack. - i = stack.length - 1; - expr = stack[i]; - while (i > 1) { - expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr); - i -= 2; - } - - return expr; - } - - - // 11.12 Conditional Operator - - function parseConditionalExpression() { - var expr, consequent, alternate; - - expr = parseBinaryExpression(); - - if (match('?')) { - lex(); - consequent = parseConditionalExpression(); - expect(':'); - alternate = parseConditionalExpression(); - - expr = delegate.createConditionalExpression(expr, consequent, alternate); - } - - return expr; - } - - // Simplification since we do not support AssignmentExpression. - var parseExpression = parseConditionalExpression; - - // Polymer Syntax extensions - - // Filter :: - // Identifier - // Identifier "(" ")" - // Identifier "(" FilterArguments ")" - - function parseFilter() { - var identifier, args; - - identifier = lex(); - - if (identifier.type !== Token.Identifier) { - throwUnexpected(identifier); - } - - args = match('(') ? parseArguments() : []; - - return delegate.createFilter(identifier.value, args); - } - - // Filters :: - // "|" Filter - // Filters "|" Filter - - function parseFilters() { - while (match('|')) { - lex(); - parseFilter(); - } - } - - // TopLevel :: - // LabelledExpressions - // AsExpression - // InExpression - // FilterExpression - - // AsExpression :: - // FilterExpression as Identifier - - // InExpression :: - // Identifier, Identifier in FilterExpression - // Identifier in FilterExpression - - // FilterExpression :: - // Expression - // Expression Filters - - function parseTopLevel() { - skipWhitespace(); - peek(); - - var expr = parseExpression(); - if (expr) { - if (lookahead.value === ',' || lookahead.value == 'in' && - expr.type === Syntax.Identifier) { - parseInExpression(expr); - } else { - parseFilters(); - if (lookahead.value === 'as') { - parseAsExpression(expr); - } else { - delegate.createTopLevel(expr); - } - } - } - - if (lookahead.type !== Token.EOF) { - throwUnexpected(lookahead); - } - } - - function parseAsExpression(expr) { - lex(); // as - var identifier = lex().value; - delegate.createAsExpression(expr, identifier); - } - - function parseInExpression(identifier) { - var indexName; - if (lookahead.value === ',') { - lex(); - if (lookahead.type !== Token.Identifier) - throwUnexpected(lookahead); - indexName = lex().value; - } - - lex(); // in - var expr = parseExpression(); - parseFilters(); - delegate.createInExpression(identifier.name, indexName, expr); - } - - function parse(code, inDelegate) { - delegate = inDelegate; - source = code; - index = 0; - length = source.length; - lookahead = null; - state = { - labelSet: {} - }; - - return parseTopLevel(); - } - - global.esprima = { - parse: parse - }; -})(this); - -// Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -// Code distributed by Google as part of the polymer project is also -// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - -(function (global) { - 'use strict'; - - function prepareBinding(expressionText, name, node, filterRegistry) { - var expression; - try { - expression = getExpression(expressionText); - if (expression.scopeIdent && - (node.nodeType !== Node.ELEMENT_NODE || - node.tagName !== 'TEMPLATE' || - (name !== 'bind' && name !== 'repeat'))) { - throw Error('as and in can only be used within