This is just a retructuring of the vscode-salesforcedx to salesforcedx-vscode.
This commit is contained in:
Nick Chen 2017-06-13 12:46:42 -07:00
Коммит 60c016028d
38 изменённых файлов: 5035 добавлений и 0 удалений

16
README.md Normal file
Просмотреть файл

@ -0,0 +1,16 @@
# Salesforce Development Tools for Visual Studio Code
## Getting Started
1. Install Visual Studio Code from https://code.visualstudio.com
1. Clone this repository using `git clone git@git.soma.salesforce.com:DevTools/vscode-salesforcedx.git`.
1. Open the cloned repository in Visual Studio Code. This is the host instance.
1. Open the integrated terminal and execute `npm install` to bring in all the Node.js dependencies.
1. Hit Cmd + Shift + B to initialize the project builder. This will build all the files that you need in the `out` directory. It also watches for any changes you make to the file and automatically compiles them.
1. Hit F5 to launch another instance of Visual Studio Code. This is a special version of Visual Studio code with the extension loaded. You can debug your things in it.
## Including your own version of the Apex Language Server
1. For the Apex Language Server, you need to issue `git clonegit@git.soma.salesforce.com:DevTools/apex-jorje.git`.
1. In the directory where you clone the previous repository, switch to the `nick/apex-lsp` branch.
1. __This part is not as smoothly automated yet__ Run the script in `scripts/pre-jars.sh` (after modifications to point it to where you have the apex-jorje source checked out).

7
lerna.json Normal file
Просмотреть файл

@ -0,0 +1,7 @@
{
"lerna": "2.0.0-rc.5",
"packages": [
"packages/*"
],
"version": "0.1.0"
}

5
package.json Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{
"devDependencies": {
"lerna": "^2.0.0-rc.5"
}
}

56
packages/salesforcedx-vscode/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,56 @@
#
# TypeScript generated files
#
dist/
#
# Istanbul code coverage files
#
coverage/
#
# https://github.com/github/gitignore/blob/master/Node.gitignore
#
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Generated vscode package
*.vsix

37
packages/salesforcedx-vscode/.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/src/**/*.js"
],
"preLaunchTask": "npm"
},
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/dist/test"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "npm"
}
]
}

10
packages/salesforcedx-vscode/.vscode/settings.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"dist": false // set this to true to hide the "dist" folder with the compiled JS files
},
"search.exclude": {
"dist": true // set this to false to include "dist" folder in search results
},
"typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
}

30
packages/salesforcedx-vscode/.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,30 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "0.1.0",
// we want to run npm
"command": "npm",
// the command is a shell script
"isShellCommand": true,
// show the output window only if unrecognized errors occur.
"showOutput": "silent",
// we run the custom script "compile" as defined in package.json
"args": ["run", "compile", "--loglevel", "silent"],
// The tsc compiler is started in watching mode
"isWatching": true,
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
"problemMatcher": "$tsc-watch"
}

Просмотреть файл

@ -0,0 +1,7 @@
tsconfig.json
.vscode/**
screenshots/**
scripts/**
src/**
dist/test/**

Просмотреть файл

@ -0,0 +1,91 @@
{
"name": "salesforcedx-vscode",
"displayName": "Salesforce Code Editor for Visual Studio Code",
"description": "Tools for developing on the Salesforce DX platform.",
"version": "0.1.0",
"publisher": "salesforce",
"license": "MIT",
"engines": {
"vscode": "^1.10.0"
},
"categories": [
"Languages",
"Debuggers",
"Other"
],
"devDependencies": {
"@types/mocha": "2.2.38",
"@types/node": "^6.0.40",
"mocha": "3.2.0",
"typescript": "2.3.4",
"vscode": "1.1.0"
},
"scripts": {
"vscode:prepublish": "tsc -p ./",
"compile": "tsc -watch -p .",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"activationEvents": [
"workspaceContains:sfdx-project.json"
],
"main": "./dist/src/salesforcedx",
"contributes": {
"commands": [
{
"command": "sfdx.force.auth.web.login",
"title": "force:auth:web:login"
},
{
"command": "sfdx.force.org.create",
"title": "force:org:create"
},
{
"command": "sfdx.force.org.open",
"title": "force:org:open"
},
{
"command": "sfdx.force.source.pull",
"title": "force:source:pull"
},
{
"command": "sfdx.force.source.push",
"title": "force:source:push"
},
{
"command": "sfdx.force.source.status",
"title": "force:source:status"
},
{
"command": "sfdx.force.apex.test.run",
"title": "force:apex:test:run"
}
],
"languages": [
{
"id": "apex",
"aliases": [
"Apex",
"apex"
],
"extensions": [
".cls",
".trigger"
],
"configuration": "./syntaxes/apex.configuration.json"
}
],
"grammars": [
{
"language": "apex",
"scopeName": "source.apex",
"path": "./syntaxes/apex.tmLanguage"
}
]
},
"dependencies": {
"expand-home-dir": "0.0.3",
"path-exists": "3.0.0",
"portfinder": "1.0.12",
"vscode-languageclient": "3.3.0"
}
}

Просмотреть файл

@ -0,0 +1,296 @@
{
"eslintrc": false,
"env": {
"browser": true
},
"parserOptions": {
"ecmaVersion": 5
},
"globals": {
"$A": true,
"AuraContext": true,
"AuraSerializationService": true,
"AuraExpressionService": true,
"AuraEventService": true,
"AuraLocalizationService": true,
"AuraStorageService": true,
"AuraStyleService": true,
"MetricsService": true,
"AuraDevToolService": true,
"Component": true,
"CKEDITOR": true,
"FORCE": true,
"moment": true,
"exports": true,
"iScroll": true,
"unescape": true,
"Promise": true
},
"rules": {
// custom rules
"ecma-intrinsics": 2,
"new-rule-template": 0,
"secure-document": 2,
"aura-api": 2,
"secure-window": 2,
// platform rules that as immutable
"no-alert": 2,
"no-array-constructor": 2, // help with instanceof
"no-bitwise": 1, // usually a typo | -> ||
"no-caller": 2, // strict mode compliance
"no-catch-shadow": 2,
"no-cond-assign": 2,
"no-console": 2,
"no-constant-condition": 2,
"no-control-regex": 1,
"no-debugger": 2,
"no-delete-var": 1, // for perf reasons, we might want to set this to 2
"no-div-regex": 1,
"no-dupe-keys": 2,
"no-dupe-args": 2,
"no-duplicate-case": 2,
"no-else-return": 0,
"no-empty-character-class": 2,
"no-eq-null": 1,
"no-eval": 2,
"no-ex-assign": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-boolean-cast": 2,
"no-fallthrough": 2, // switch fallthrough
"no-floating-decimal": 1, // var num = .5;
"no-func-assign": 2,
"no-implied-eval": 2,
"no-inner-declarations": [
2,
"functions"
],
"no-invalid-regexp": 2,
"no-irregular-whitespace": 2,
"no-iterator": 2,
"no-label-var": 2,
"no-labels": 2,
"no-loop-func": 2,
"no-multi-str": 2,
"no-native-reassign": 2,
"no-negated-in-lhs": 2,
"no-nested-ternary": 1,
"no-new": 2,
"no-new-func": 2,
"no-new-object": 2,
"no-new-wrappers": 2,
"no-obj-calls": 2,
"no-octal": 2,
"no-octal-escape": 2,
"no-param-reassign": 1,
"no-plusplus": 1,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-return-assign": 2,
"no-script-url": 2,
"no-self-compare": 2,
"no-sequences": 2, // var a = (3, 5);
"no-shadow": 2,
"no-shadow-restricted-names": 2,
"no-sparse-arrays": 2,
"no-ternary": 0,
"no-throw-literal": 1,
"no-undef": 1,
"no-undef-init": 1,
"no-undefined": 0,
"no-underscore-dangle": 0,
"no-unreachable": 2,
"no-unused-expressions": 0,
"no-unused-vars": [
1,
{
"vars": "all",
"args": "after-used"
}
],
"no-use-before-define": [
2,
{
"functions": false
}
],
"no-void": 2,
"no-var": 0,
"no-with": 2,
"consistent-return": 1,
"default-case": 2,
"dot-notation": [
1,
{
"allowKeywords": true
}
],
"eqeqeq": [
"error",
"smart"
],
"guard-for-in": 1,
"handle-callback-err": 1,
"new-parens": 2,
"radix": 2,
"strict": [
2,
"global"
],
"use-isnan": 2,
"valid-typeof": 2,
"wrap-iife": [
1,
"any"
],
// aside from this list, ./code-style-rules.js will have the rules that are not
// important for the code to function, but just stylish.
// code style rules, these are the default value, but the user can
// customize them via --config in the linter by providing custom values
// for each of these rules.
"no-trailing-spaces": 1,
"no-spaced-func": 1,
"no-mixed-spaces-and-tabs": 0,
"no-multi-spaces": 0,
"no-multiple-empty-lines": 0,
"no-lone-blocks": 1,
"no-lonely-if": 1,
"no-inline-comments": 0,
"no-extra-parens": 0,
"no-extra-semi": 1,
"no-warning-comments": [
0,
{
"terms": [
"todo",
"fixme",
"xxx"
],
"location": "start"
}
],
"block-scoped-var": 1,
"brace-style": [
1,
"1tbs"
],
"camelcase": 1,
"comma-dangle": [
1,
"never"
],
"comma-spacing": 1,
"comma-style": 1,
"complexity": [
0,
11
],
"consistent-this": [
0,
"that"
],
"curly": [
1,
"all"
],
"eol-last": 0,
"func-names": 0,
"func-style": [
0,
"declaration"
],
"generator-star-spacing": 0,
"indent": 0,
"key-spacing": 0,
"keyword-spacing": [
0
],
"max-depth": [
0,
4
],
"max-len": [
0,
80,
4
],
"max-nested-callbacks": [
0,
2
],
"max-params": [
0,
3
],
"max-statements": [
0,
10
],
"new-cap": 0,
"newline-after-var": 0,
"one-var": [
0,
"never"
],
"operator-assignment": [
0,
"always"
],
"padded-blocks": 0,
"quote-props": 0,
"quotes": 0,
"semi": 1,
"semi-spacing": [
0,
{
"before": false,
"after": true
}
],
"sort-vars": 0,
"space-after-function-name": [
0,
"never"
],
"space-before-blocks": [
0,
"always"
],
"space-before-function-paren": [
0,
"always"
],
"space-before-function-parentheses": [
0,
"always"
],
"space-in-brackets": [
0,
"never"
],
"space-in-parens": [
0,
"never"
],
"space-infix-ops": 0,
"space-unary-ops": [
1,
{
"words": true,
"nonwords": false
}
],
"spaced-comment": [
0,
"always"
],
"vars-on-top": 0,
"valid-jsdoc": 0,
"wrap-regex": 0,
"yoda": [
1,
"never"
]
}
}

Просмотреть файл

@ -0,0 +1,594 @@
// Copyright (C) 2011 Google Inc.
//
// 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.
/**
* @fileoverview Exports {@code ses.whitelist}, a recursively defined
* JSON record enumerating all the naming paths in the ES5.1 spec,
* those de-facto extensions that we judge to be safe, and SES and
* Dr. SES extensions provided by the SES runtime.
*
* <p>Assumes only ES3. Compatible with ES5, ES5-strict, or
* anticipated ES6.
*
* //provides ses.whitelist
* @author Mark S. Miller,
* @overrides ses, whitelistModule
*/
var ses = {}; module.exports = ses; // custom line to make it work in node env.
/**
* <p>Each JSON record enumerates the disposition of the properties on
* some corresponding primordial object, with the root record
* representing the global object. For each such record, the values
* associated with its property names can be
* <ul>
* <li>Another record, in which case this property is simply
* whitelisted and that next record represents the disposition of
* the object which is its value. For example, {@code "Object"}
* leads to another record explaining what properties {@code
* "Object"} may have and how each such property, if present,
* and its value should be tamed.
* <li>true, in which case this property is simply whitelisted. The
* value associated with that property is still traversed and
* tamed, but only according to the taming of the objects that
* object inherits from. For example, {@code "Object.freeze"} leads
* to true, meaning that the {@code "freeze"} property of {@code
* Object} should be whitelisted and the value of the property (a
* function) should be further tamed only according to the
* markings of the other objects it inherits from, like {@code
* "Function.prototype"} and {@code "Object.prototype").
* If the property is an accessor property, it is not
* whitelisted (as invoking an accessor might not be meaningful,
* yet the accessor might return a value needing taming).
* <li>"maybeAccessor", in which case this accessor property is simply
* whitelisted and its getter and/or setter are tamed according to
* inheritance. If the property is not an accessor property, its
* value is tamed according to inheritance.
* <li>"*", in which case this property on this object is whitelisted,
* as is this property as inherited by all objects that inherit
* from this object. The values associated with all such properties
* are still traversed and tamed, but only according to the taming
* of the objects that object inherits from. For example, {@code
* "Object.prototype.constructor"} leads to "*", meaning that we
* whitelist the {@code "constructor"} property on {@code
* Object.prototype} and on every object that inherits from {@code
* Object.prototype} that does not have a conflicting mark. Each
* of these is tamed as if with true, so that the value of the
* property is further tamed according to what other objects it
* inherits from.
* <li>false, which suppression permission inherited via "*".
* </ul>
*
* <p>TODO: We want to do for constructor: something weaker than '*',
* but rather more like what we do for [[Prototype]] links, which is
* that it is whitelisted only if it points at an object which is
* otherwise reachable by a whitelisted path.
*
* <p>The members of the whitelist are either
* <ul>
* <li>(uncommented) defined by the ES5.1 normative standard text,
* <li>(questionable) provides a source of non-determinism, in
* violation of pure object-capability rules, but allowed anyway
* since we've given up on restricting JavaScript to a
* deterministic subset.
* <li>(ES5 Appendix B) common elements of de facto JavaScript
* described by the non-normative Appendix B.
* <li>(Harmless whatwg) extensions documented at
* <a href="http://wiki.whatwg.org/wiki/Web_ECMAScript"
* >http://wiki.whatwg.org/wiki/Web_ECMAScript</a> that seem to be
* harmless. Note that the RegExp constructor extensions on that
* page are <b>not harmless</b> and so must not be whitelisted.
* <li>(ES-Harmony proposal) accepted as "proposal" status for
* EcmaScript-Harmony.
* </ul>
*
* <p>With the above encoding, there are some sensible whitelists we
* cannot express, such as marking a property both with "*" and a JSON
* record. This is an expedient decision based only on not having
* encountered such a need. Should we need this extra expressiveness,
* we'll need to refactor to enable a different encoding.
*
* <p>We factor out {@code true} into the variable {@code t} just to
* get a bit better compression from simple minifiers.
*/
(function whitelistModule() {
"use strict";
if (!ses) { ses = {}; }
var t = true;
var TypedArrayWhitelist; // defined and used below
ses.whitelist = {
cajaVM: { // Caja support
// The accessible intrinsics which are not reachable by own
// property name traversal are listed here so that they are
// processed by the whitelist, although this also makes them
// accessible by this path. See
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-well-known-intrinsic-objects
// Of these, ThrowTypeError is the only one from ES5. All the
// rest were introduced in ES6.
anonIntrinsics: {
ThrowTypeError: {},
IteratorPrototype: {
// Technically, for SES-on-ES5, we should not need to
// whitelist 'next'. However, browsers are accidentally
// relying on it
// https://bugs.chromium.org/p/v8/issues/detail?id=4769#
// https://bugs.webkit.org/show_bug.cgi?id=154475
// and we will be whitelisting it as we transition to ES6
// anyway, so we unconditionally whitelist it now.
next: '*',
constructor: false
},
ArrayIteratorPrototype: {},
StringIteratorPrototype: {},
// TODO MapIteratorPrototype: {},
// TODO SetIteratorPrototype: {},
// The %GeneratorFunction% intrinsic is the constructor of
// generator functions, so %GeneratorFunction%.prototype is
// the %Generator% intrinsic, which all generator functions
// inherit from. A generator function is effectively the
// constructor of its generator instances, so, for each
// generator function (e.g., "g1" on the diagram at
// http://people.mozilla.org/~jorendorff/figure-2.png )
// its .prototype is a prototype that its instances inherit
// from. Paralleling this structure, %Generator%.prototype,
// i.e., %GeneratorFunction%.prototype.prototype, is the
// object that all these generator function prototypes inherit
// from. The .next, .return and .throw that generator
// instances respond to are actually the builtin methods they
// inherit from this object.
GeneratorFunction: {
prototype: {
prototype: {
next: '*',
'return': '*',
'throw': '*'
}
}
},
TypedArray: TypedArrayWhitelist = {
length: '*', // does not inherit from Function.prototype on Chrome
name: '*', // ditto
BYTES_PER_ELEMENT: '*',
from: t,
of: t,
prototype: {
buffer: 'maybeAccessor',
byteOffset: 'maybeAccessor',
byteLength: 'maybeAccessor',
length: 'maybeAccessor',
BYTES_PER_ELEMENT: '*',
set: '*',
subarray: '*'
}
}
},
log: t,
tamperProof: t,
constFunc: t,
Nat: t,
def: t,
is: t,
compileExpr: t,
confine: t,
compileModule: t, // experimental
compileProgram: t, // Cannot be implemented in just ES5.1.
eval: t,
Function: t,
sharedImports: t,
makeImports: t,
copyToImports: t,
GuardT: {
coerce: t
},
makeTableGuard: t,
Trademark: {
stamp: t
},
guard: t,
passesGuard: t,
stamp: t,
makeSealerUnsealerPair: t,
makeArrayLike: {
canBeFullyLive: t
}
},
WeakMap: { // ES-Harmony proposal as currently implemented by FF6.0a1
prototype: {
// Note: coordinate this list with maintenance of repairES5.js
get: t,
set: t,
has: t,
'delete': t
}
},
StringMap: { // A specialized approximation of ES-Harmony's Map.
prototype: {} // Technically, the methods should be on the prototype,
// but doing so while preserving encapsulation will be
// needlessly expensive for current usage.
},
// As of this writing, the WeakMap emulation in WeakMap.js relies on
// the unguessability and undiscoverability of HIDDEN_NAME, a
// secret property name. However, on a platform with built-in
// Proxies, if whitelisted but not properly monkey patched, proxies
// could be used to trap and thereby discover HIDDEN_NAME. So until we
// (TODO(erights)) write the needed monkey patching of proxies, we
// omit them from our whitelist.
//
// We now have an additional reason to omit Proxy from the whitelist.
// The makeBrandTester in repairES5 uses Allen's trick at
// https://esdiscuss.org/topic/tostringtag-spoofing-for-null-and-undefined#content-59
// , but testing reveals that, on FF 35.0.1, a proxy on an exotic
// object X will pass this brand test when X will. This is fixed as of
// FF Nightly 38.0a1.
//
// Proxy: { // ES-Harmony proposal
// create: t,
// createFunction: t
// },
escape: t, // ES5 Appendix B
unescape: t, // ES5 Appendix B
Object: {
// If any new methods are added here that may reveal the
// HIDDEN_NAME within WeakMap.js, such as the proposed
// getOwnPropertyDescriptors or getPropertyDescriptors, then
// extend WeakMap.js to monkey patch these to avoid revealing
// HIDDEN_NAME.
assign: t,
getPropertyDescriptor: t, // ES-Harmony proposal
getPropertyNames: t, // ES-Harmony proposal
is: t, // ES-Harmony proposal
prototype: {
// Whitelisted only to work around a Chrome debugger
// stratification bug (TODO(erights): report). These are
// redefined in startSES.js in terms of standard methods, so
// that we can be confident they introduce no non-standard
// possibilities.
__defineGetter__: t,
__defineSetter__: t,
__lookupGetter__: t,
__lookupSetter__: t,
// There are only here to support repair_THROWING_THAWS_FROZEN_OBJECT,
// which repairs Safari-only bug
// https://bugs.webkit.org/show_bug.cgi?id=141878 by
// preemptively adding these properties to any objects that
// are about to become non-extensible. When these are already
// present, then the Safari bug does not add them.
line: '*',
column: '*',
sourceUrl: '*',
stack: '*',
constructor: '*',
toString: '*',
toLocaleString: '*',
valueOf: t,
hasOwnProperty: t,
isPrototypeOf: t,
propertyIsEnumerable: t
},
getPrototypeOf: t,
getOwnPropertyDescriptor: t,
getOwnPropertyNames: t,
create: t,
defineProperty: t,
defineProperties: t,
seal: t,
freeze: t,
preventExtensions: t,
isSealed: t,
isFrozen: t,
isExtensible: t,
keys: t
},
NaN: t,
Infinity: t,
undefined: t,
// eval: t, // Whitelisting under separate control
// by TAME_GLOBAL_EVAL in startSES.js
parseInt: t,
parseFloat: t,
isNaN: t,
isFinite: t,
decodeURI: t,
decodeURIComponent: t,
encodeURI: t,
encodeURIComponent: t,
Function: {
prototype: {
apply: t,
call: t,
bind: t,
prototype: '*',
length: '*',
arity: '*', // non-std, deprecated in favor of length
name: '*' // non-std
}
},
Array: {
prototype: {
concat: t,
join: t,
pop: t,
push: t,
reverse: t,
shift: t,
slice: t,
sort: t,
splice: t,
unshift: t,
indexOf: t,
lastIndexOf: t,
every: t,
some: t,
forEach: t,
map: t,
filter: t,
reduce: t,
reduceRight: t,
length: t
},
isArray: t
},
String: {
prototype: {
substr: t, // ES5 Appendix B
anchor: t, // Harmless whatwg
big: t, // Harmless whatwg
blink: t, // Harmless whatwg
bold: t, // Harmless whatwg
fixed: t, // Harmless whatwg
fontcolor: t, // Harmless whatwg
fontsize: t, // Harmless whatwg
italics: t, // Harmless whatwg
link: t, // Harmless whatwg
small: t, // Harmless whatwg
strike: t, // Harmless whatwg
sub: t, // Harmless whatwg
sup: t, // Harmless whatwg
trimLeft: t, // non-standard
trimRight: t, // non-standard
valueOf: t,
charAt: t,
charCodeAt: t,
concat: t,
indexOf: t,
lastIndexOf: t,
localeCompare: t,
match: t,
replace: t,
search: t,
slice: t,
split: t,
substring: t,
toLowerCase: t,
toLocaleLowerCase: t,
toUpperCase: t,
toLocaleUpperCase: t,
trim: t,
length: '*'
},
fromCharCode: t
},
Boolean: {
prototype: {
valueOf: t
}
},
Number: {
prototype: {
valueOf: t,
toFixed: t,
toExponential: t,
toPrecision: t
},
MAX_VALUE: t,
MIN_VALUE: t,
NaN: t,
NEGATIVE_INFINITY: t,
POSITIVE_INFINITY: t
},
Math: {
E: t,
LN10: t,
LN2: t,
LOG2E: t,
LOG10E: t,
PI: t,
SQRT1_2: t,
SQRT2: t,
abs: t,
acos: t,
asin: t,
atan: t,
atan2: t,
ceil: t,
cos: t,
exp: t,
floor: t,
log: t,
max: t,
min: t,
pow: t,
random: t, // questionable
round: t,
sin: t,
sqrt: t,
tan: t
},
Date: { // no-arg Date constructor is questionable
prototype: {
// Note: coordinate this list with maintanence of repairES5.js
getYear: t, // ES5 Appendix B
setYear: t, // ES5 Appendix B
toGMTString: t, // ES5 Appendix B
toDateString: t,
toTimeString: t,
toLocaleString: t,
toLocaleDateString: t,
toLocaleTimeString: t,
valueOf: t,
getTime: t,
getFullYear: t,
getUTCFullYear: t,
getMonth: t,
getUTCMonth: t,
getDate: t,
getUTCDate: t,
getDay: t,
getUTCDay: t,
getHours: t,
getUTCHours: t,
getMinutes: t,
getUTCMinutes: t,
getSeconds: t,
getUTCSeconds: t,
getMilliseconds: t,
getUTCMilliseconds: t,
getTimezoneOffset: t,
setTime: t,
setFullYear: t,
setUTCFullYear: t,
setMonth: t,
setUTCMonth: t,
setDate: t,
setUTCDate: t,
setHours: t,
setUTCHours: t,
setMinutes: t,
setUTCMinutes: t,
setSeconds: t,
setUTCSeconds: t,
setMilliseconds: t,
setUTCMilliseconds: t,
toUTCString: t,
toISOString: t,
toJSON: t
},
parse: t,
UTC: t,
now: t // questionable
},
RegExp: {
prototype: {
exec: t,
test: t,
source: 'maybeAccessor',
global: 'maybeAccessor',
ignoreCase: 'maybeAccessor',
multiline: 'maybeAccessor',
flags: 'maybeAccessor',
unicode: 'maybeAccessor',
lastIndex: '*',
options: '*', // non-std
sticky: 'maybeAccessor' // non-std
}
},
Error: {
prototype: {
name: '*',
message: '*'
}
},
// In ES6 the *Error "subclasses" of Error inherit from Error,
// since constructor inheritance generally mirrors prototype
// inheritance. As explained at
// https://code.google.com/p/google-caja/issues/detail?id=1963 ,
// debug.js hides away the Error constructor itself, and so needs
// to rewire these "subclass" constructors. Until we have a more
// general mechanism, please maintain this list of whitelisted
// subclasses in sync with the list in debug.js of subclasses to
// be rewired.
EvalError: {
prototype: t
},
RangeError: {
prototype: t
},
ReferenceError: {
prototype: t
},
SyntaxError: {
prototype: t
},
TypeError: {
prototype: t
},
URIError: {
prototype: t
},
JSON: {
parse: t,
stringify: t
},
///////////////// Standard Starting in ES6 //////////////////
ArrayBuffer: { // Khronos Typed Arrays spec; ops are safe
length: t, // does not inherit from Function.prototype on Chrome
name: t, // ditto
isView: t,
prototype: {
byteLength: 'maybeAccessor',
slice: t
}
},
Int8Array: TypedArrayWhitelist,
Uint8Array: TypedArrayWhitelist,
Uint8ClampedArray: TypedArrayWhitelist,
Int16Array: TypedArrayWhitelist,
Uint16Array: TypedArrayWhitelist,
Int32Array: TypedArrayWhitelist,
Uint32Array: TypedArrayWhitelist,
Float32Array: TypedArrayWhitelist,
Float64Array: TypedArrayWhitelist,
DataView: { // Typed Arrays spec
length: t, // does not inherit from Function.prototype on Chrome
name: t, // ditto
prototype: {
buffer: 'maybeAccessor',
byteOffset: 'maybeAccessor',
byteLength: 'maybeAccessor',
getInt8: t,
getUint8: t,
getInt16: t,
getUint16: t,
getInt32: t,
getUint32: t,
getFloat32: t,
getFloat64: t,
setInt8: t,
setUint8: t,
setInt16: t,
setUint16: t,
setInt32: t,
setUint32: t,
setFloat32: t,
setFloat64: t
}
}
};
})();

Просмотреть файл

@ -0,0 +1,151 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
// to guarantee that all custom rules are loaded before creating the config
require('./load-rules.js');
var ERROR = 2;
var WARNING = 1;
var IGNORE = 0;
// eslint config
module.exports = {
version: false,
eslintrc: false,
env: {
browser: true
},
parserOptions: {
ecmaVersion: 5
},
globals: {
"$A": true,
"AuraContext": true,
"AuraSerializationService": true,
"AuraExpressionService": true,
"AuraEventService": true,
"AuraLocalizationService": true,
"AuraStorageService": true,
"AuraStyleService": true,
"MetricsService": true,
"AuraDevToolService": true,
"Component": true,
"CKEDITOR": true,
"FORCE": true,
"moment": true,
"exports": true,
"iScroll": true,
"unescape": true,
"Promise": true
},
rules: {
// custom rules
"ecma-intrinsics": ERROR,
"new-rule-template": IGNORE,
"secure-document": ERROR,
"aura-api": ERROR,
"secure-window": ERROR,
// platform rules that as immutable
"no-alert": ERROR,
"no-array-constructor": ERROR, // help with instanceof
"no-bitwise": WARNING, // usually a typo | -> ||
"no-caller": ERROR, // strict mode compliance
"no-catch-shadow": ERROR,
"no-cond-assign": ERROR,
"no-console": ERROR,
"no-constant-condition": ERROR,
"no-control-regex": WARNING,
"no-debugger": ERROR,
"no-delete-var": WARNING, // for perf reasons, we might want to set this to 2
"no-div-regex": WARNING,
"no-dupe-keys": ERROR,
"no-dupe-args": ERROR,
"no-duplicate-case": ERROR,
"no-else-return": IGNORE,
"no-empty-character-class": ERROR,
"no-eq-null": WARNING,
"no-eval": ERROR,
"no-ex-assign": ERROR,
"no-extend-native": ERROR,
"no-extra-bind": ERROR,
"no-extra-boolean-cast": ERROR,
"no-fallthrough": ERROR, // switch fallthrough
"no-floating-decimal": WARNING, // var num = .5;
"no-func-assign": ERROR,
"no-implied-eval": ERROR,
"no-inner-declarations": [ERROR, "functions"],
"no-invalid-regexp": ERROR,
"no-irregular-whitespace": ERROR,
"no-iterator": ERROR,
"no-label-var": ERROR,
"no-labels": ERROR,
"no-loop-func": ERROR,
"no-multi-str": ERROR,
"no-native-reassign": ERROR,
"no-negated-in-lhs": ERROR,
"no-nested-ternary": WARNING,
"no-new": ERROR,
"no-new-func": ERROR,
"no-new-object": ERROR,
"no-new-wrappers": ERROR,
"no-obj-calls": ERROR,
"no-octal": ERROR,
"no-octal-escape": ERROR,
"no-param-reassign": WARNING,
"no-plusplus": WARNING,
"no-proto": ERROR,
"no-redeclare": ERROR,
"no-regex-spaces": ERROR,
"no-return-assign": ERROR,
"no-script-url": ERROR,
"no-self-compare": ERROR,
"no-sequences": ERROR, // var a = (3, 5);
"no-shadow": ERROR,
"no-shadow-restricted-names": ERROR,
"no-sparse-arrays": ERROR,
"no-ternary": IGNORE,
"no-throw-literal": WARNING,
"no-undef": WARNING,
"no-undef-init": WARNING,
"no-undefined": IGNORE,
"no-underscore-dangle": IGNORE,
"no-unreachable": ERROR,
"no-unused-expressions": WARNING,
"no-unused-vars": [WARNING, {"vars": "all", "args": "after-used"}],
"no-use-before-define": [ERROR, { "functions": false }],
"no-void": ERROR,
"no-var": IGNORE,
"no-with": ERROR,
"consistent-return": WARNING,
"default-case": ERROR,
"dot-notation": [WARNING, { "allowKeywords": true }],
"eqeqeq": ["error", "smart"],
"guard-for-in": WARNING,
"handle-callback-err": WARNING,
"new-parens": ERROR,
"radix": ERROR,
"strict": [ERROR, "global"],
"use-isnan": ERROR,
"valid-typeof": ERROR,
"wrap-iife": [WARNING, "any"]
// aside from this list, ./code-style-rules.js will have the rules that are not
// important for the code to function, but just stylish.
}
};

Просмотреть файл

@ -0,0 +1,78 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
module.exports = {
rules: {
// code style rules, these are the default value, but the user can
// customize them via --config in the linter by providing custom values
// for each of these rules.
"no-trailing-spaces": 1,
"no-spaced-func": 1,
"no-mixed-spaces-and-tabs": 0,
"no-multi-spaces": 0,
"no-multiple-empty-lines": 0,
"no-lone-blocks": 1,
"no-lonely-if": 1,
"no-inline-comments": 0,
"no-extra-parens": 0,
"no-extra-semi": 1,
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
"block-scoped-var": 1,
"brace-style": [1, "1tbs"],
"camelcase": 1,
"comma-dangle": [1, "never"],
"comma-spacing": 1,
"comma-style": 1,
"complexity": [0, 11],
"consistent-this": [0, "that"],
"curly": [1, "all"],
"eol-last": 0,
"func-names": 0,
"func-style": [0, "declaration"],
"generator-star-spacing": 0,
"indent": 0,
"key-spacing": 0,
"keyword-spacing": [0],
"max-depth": [0, 4],
"max-len": [0, 80, 4],
"max-nested-callbacks": [0, 2],
"max-params": [0, 3],
"max-statements": [0, 10],
"new-cap": 0,
"newline-after-var": 0,
"one-var": [0, "never"],
"operator-assignment": [0, "always"],
"padded-blocks": 0,
"quote-props": 0,
"quotes": 0,
"semi": 1,
"semi-spacing": [0, {"before": false, "after": true}],
"sort-vars": 0,
"space-after-function-name": [0, "never"],
"space-before-blocks": [0, "always"],
"space-before-function-paren": [0, "always"],
"space-before-function-parentheses": [0, "always"],
"space-in-brackets": [0, "never"],
"space-in-parens": [0, "never"],
"space-infix-ops": 0,
"space-unary-ops": [1, { "words": true, "nonwords": false }],
"spaced-comment": [0, "always"],
"vars-on-top": 0,
"valid-jsdoc": 0,
"wrap-regex": 0,
"yoda": [1, "never"]
}
};

Просмотреть файл

@ -0,0 +1,25 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
var defaultConfig = require('./aura-component-config');
var defaultStyle = require('./code-style-rules');
var objectAssign = require('object-assign');
var config = {};
objectAssign(config, defaultConfig);
objectAssign(config.rules, defaultStyle.rules);
module.exports = config;

Просмотреть файл

@ -0,0 +1,97 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
module.exports = {
// Standard Global Event handlers
// https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers
onabort: true,
onblur: true,
onchange: true,
onclick: true,
onclose: true,
oncontextmenu: true,
ondblclick: true,
onerror: true,
onfocus: true,
oninput: true,
onkeydown: true,
onkeypress: true,
onkeyup: true,
onload: true,
onmousedown: true,
onmousemove: true,
onmouseout: true,
onmouseover: true,
onmouseup: true,
onreset: true,
onresize: true,
onscroll: true,
onselect: true,
onsubmit: true,
// Standard Element interface represents an object of a Document.
// https://developer.mozilla.org/en-US/docs/Web/API/Element#Properties
childElementCount: '*',
classList: '*',
className: '*',
id: '*',
tagName: '*',
namespaceURI: '*',
// Note: ignoring 'firstElementChild', 'lastElementChild',
// 'nextElementSibling' and 'previousElementSibling' from the list
// above.
// Standard HTMLElement interface represents any HTML element
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement#Properties
accessKey: '*',
accessKeyLabel: '*',
contentEditable: '*',
isContentEditable: '*',
contextMenu: '*',
dataset: '*',
dir: '*',
draggable: '*',
dropzone: '*',
hidden: '*',
lang: '*',
spellcheck: '*',
style: '*',
tabIndex: '*',
title: '*',
offsetHeight: '*',
offsetLeft: '*',
offsetParent: '*',
offsetTop: '*',
offsetWidth: '*',
clientWidth: '*',
clientHeight: '*',
clientLeft: '*',
clientTop: '*',
nodeValue: '*',
nodeType: '*',
childNodes: '*',
// other DOM methods
getElementById: true,
getElementsByClassName: true,
getElementsByName: true,
getElementsByTagName: true,
getElementsByTagNameNS: true,
querySelector: true,
querySelectorAll: true
};

Просмотреть файл

@ -0,0 +1,24 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
module.exports = {
// event target methods
addEventListener: true,
dispatchEvent: true,
removeEventListener: true
}

Просмотреть файл

@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
module.exports = {
// Standard Global Event handlers
// https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers
onabort: true,
onblur: true,
onchange: true,
onclick: true,
onclose: true,
oncontextmenu: true,
ondblclick: true,
onerror: true,
onfocus: true,
oninput: true,
onkeydown: true,
onkeypress: true,
onkeyup: true,
onload: true,
onmousedown: true,
onmousemove: true,
onmouseout: true,
onmouseover: true,
onmouseup: true,
onreset: true,
onresize: true,
onscroll: true,
onselect: true,
onsubmit: true
}

Просмотреть файл

@ -0,0 +1,66 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
module.exports = {
// Standard Node APIs
// https://developer.mozilla.org/en-US/docs/Web/API/Node
ATTRIBUTE_NODE: '*',
CDATA_SECTION_NODE: '*',
COMMENT_NODE: '*',
DOCUMENT_FRAGMENT_NODE: '*',
DOCUMENT_NODE: '*',
DOCUMENT_POSITION_CONTAINED_BY: '*',
DOCUMENT_POSITION_CONTAINS: '*',
DOCUMENT_POSITION_DISCONNECTED: '*',
DOCUMENT_POSITION_FOLLOWING: '*',
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: '*',
DOCUMENT_POSITION_PRECEDING: '*',
DOCUMENT_TYPE_NODE: '*',
ELEMENT_NODE: '*',
ENTITY_NODE: '*',
ENTITY_REFERENCE_NODE: '*',
NOTATION_NODE: '*',
PROCESSING_INSTRUCTION_NODE: '*',
TEXT_NODE: '*',
appendChild: true,
baseURI: '*',
childNodes: '*',
cloneNode: true,
compareDocumentPosition: true,
contains: true,
firstChild: '*',
insertBefore: true,
isDefaultNamespace: true,
isEqualNode: true,
isSameNode: true,
lastChild: '*',
lookupNamespaceURI: true,
lookupPrefix: true,
nextSibling: '*',
nodeName: '*',
nodeType: '*',
nodeValue: '*',
normalize: true,
ownerDocument: '*',
parentElement: '*',
parentNode: '*',
previousSibling: '*',
removeChild: true,
replaceChild: true,
textContent: '*'
};

Просмотреть файл

@ -0,0 +1,210 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
var glob = require('glob');
var path = require('path');
var fs = require('fs');
var cli = require('heroku-cli-util');
var linter = require('eslint').linter;
var defaultConfig = require('./config');
var defaultStyle = require('./code-style-rules');
var objectAssign = require('object-assign');
var formatter = require('eslint-friendly-formatter');
var SINGLETON_FILE_REGEXP = /(Controller|Renderer|Helper|Provider|Test|Model)\.js$/;
function noop() {}
// this computes the first position after all the comments (multi-line and single-line)
// from the top of the code
function afterCommentsPosition(code) {
var position = 0;
var match;
do {
// /\*.*?\*/
match = code.match(/^(\s*(\/\*([\s\S]*?)\*\/)?\s*)/);
if (!match || !match[1]) {
match = code.match(/^(\s*\/\/.*\s*)/);
}
if (match && match[1]) {
position += match[1].length;
code = code.slice(match[1].length);
}
} while (match);
return position;
}
function processSingletonCode(code) {
// transform `({...})` into `"use strict"; exports = ({...});`
var pos = afterCommentsPosition(code);
if (code.charAt(pos) === '(') {
code = code.slice(0, pos) + '"use strict"; exports = ' + code.slice(pos);
pos = code.lastIndexOf(')') + 1;
if (code.charAt(pos) !== ';') {
code = code.slice(0, pos) + ';' + code.slice(pos);
}
}
return code;
}
function processFunctionCode(code) {
// transform `function () {}` into `"use strict"; exports = function () {};`
var pos = afterCommentsPosition(code);
if (code.indexOf('function', pos) === pos) {
code = code.slice(0, pos) + '"use strict"; exports = ' + code.slice(pos);
pos = code.lastIndexOf('}') + 1;
if (code.charAt(pos) !== ';') {
code = code.slice(0, pos) + ';' + code.slice(pos);
}
}
return code;
}
function process(src, config, options) {
var messages = linter.verify(src, config, {
allowInlineConfig: true, // TODO: internal code should be linted with this set to false
quiet: true
});
if (!options.verbose) {
messages = messages.filter(function (msg) {
return msg.severity > 1;
});
}
return messages;
}
module.exports = function (cwd, opts, context) {
// No log, debug or warn functions if --json option is passed
var log = opts.json ? noop : cli.log;
var debug = opts.json ? noop : cli.debug;
var warn = opts.json ? noop : cli.warn;
var ignore = [
// these are the things that we know for sure we never want to inspect
'**/node_modules/**',
'**/jsdoc/**',
'**/htdocs/**',
'**/invalidTest/**',
'**/purposelyInvalid/**',
'**/invalidTestData/**',
'**/validationTest/**',
'**/lintTest/**',
'**/target/**',
'**/parseError/**',
'**/*.junk.js',
'**/*_mock?.js'
].concat(opts.ignore ? [opts.ignore] : []);
var globOptions = {
silent: true,
cwd: cwd,
nodir: true,
realpath: true,
ignore: ignore
};
var patterns = [opts.files || '**/*.js'];
var config = {};
objectAssign(config, defaultConfig);
config.rules = objectAssign({}, defaultConfig.rules);
if (opts.config) {
log('Applying custom rules from ' + opts.config);
var customStyle = require(path.join(context.cwd, opts.config));
if (customStyle && customStyle.rules) {
Object.keys(customStyle.rules).forEach(function (name) {
if (defaultStyle.rules.hasOwnProperty(name)) {
config.rules[name] = customStyle.rules[name];
debug(' -> Rule: ' + name + ' is now set to ' + JSON.stringify(config.rules[name]));
} else {
debug(' -> Ignoring non-style rule: ' + name);
}
});
}
}
// Using local debug function for non-json text
debug('Search for "' + patterns.join('" or "') + '" in folder "' + cwd + '"');
debug(' -> Ignoring: ' + ignore.join(','));
var files = [];
// for blt-like structures we look for aura structures
// and we search from there to narrow down the search.
var folders = glob.sync('**/*.{app,cmp,lib}', globOptions);
folders = folders.map(function (v) {
return path.dirname(v);
});
folders = folders.filter(function (v, i) {
return folders.indexOf(v) === i;
});
folders.forEach(function (folder) {
globOptions.cwd = folder;
patterns.forEach(function (pattern) {
files = files.concat(glob.sync(pattern, globOptions));
});
});
// deduping...
files = files.filter(function (v, i) {
return files.indexOf(v) === i;
});
if (files.length) {
log('Found ' + files.length + ' matching files.\n----------------');
var output = [];
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf8');
// in some cases, we need to massage the source before linting it
if (SINGLETON_FILE_REGEXP.test(file)) {
source = processSingletonCode(source);
} else {
source = processFunctionCode(source);
}
var messages = process(source, config, opts);
if (messages) {
if (opts.json) {
output.push({
file: file,
result: messages
})
} else {
log('FILE: ' + file + ':');
log(formatter([{
messages: messages,
filePath: '<input>'
}]).replace(/<input>/g, 'Line'));
}
}
});
// printout JSON string to STDOUT
if (opts.json) {
cli.log(JSON.stringify(output, null, 4));
}
} else {
warn('Did not find matching files.');
}
}

Просмотреть файл

@ -0,0 +1,27 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
var rules = require('eslint/lib/rules');
var ruleLoader = require('eslint/lib/load-rules');
var customRules = ruleLoader('../rules', __dirname);
Object.keys(customRules).forEach(function (name) {
rules.define(name, customRules[name]);
});
module.exports = rules;

Просмотреть файл

@ -0,0 +1,109 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
/**
* Returns the property name of a MemberExpression.
* @param {ASTNode} memberExpressionNode The MemberExpression node.
* @returns {string|null} Returns the property name if available, null else.
*/
function getPropertyName(memberExpressionNode) {
if (memberExpressionNode.computed) {
if (memberExpressionNode.property.type === "Literal") {
return memberExpressionNode.property.value;
}
} else {
return memberExpressionNode.property.name;
}
return null;
}
/**
* Finds the escope reference in the given scope.
* @param {Object} scope The scope to search.
* @param {ASTNode} node The identifier node.
* @returns {Reference|null} Returns the found reference or null if none were found.
*/
function findReference(scope, node) {
var references = scope.references.filter(function(reference) {
return reference.identifier.range[0] === node.range[0] &&
reference.identifier.range[1] === node.range[1];
});
if (references.length === 1) {
return references[0];
}
return null;
}
/**
* Checks if the given identifier node is shadowed in the given scope.
* @param {Object} scope The current scope.
* @param {Object} globalScope The global scope.
* @param {string} node The identifier node to check
* @returns {boolean} Whether or not the name is shadowed.
*/
function isShadowed(scope, globalScope, node) {
var reference = findReference(scope, node);
return reference && reference.resolved && reference.resolved.defs.length > 0;
}
/**
* Finds all the nodes used by a composed member expression.
* E.g.: Array.prototype.slice should produce
* [{type: "Identifier", name: "Array"}, {type: "Identifier", name: "prototype"}, {type: "Identifier", name: "slice"}]
* @param {ASTNode} node The MemberExpression node.
* @returns {Array} Returns a list of nodes that represent the namespace.
*/
function buildMemberExpressionNamespace(currentScope, globalScope, node) {
var ns = [];
do {
ns.unshift(node.property);
if (node.object.type === "MemberExpression") {
node = node.object;
} else if (!isGlobalThisReferenceOrGlobalWindow(currentScope, globalScope, node.object)) {
ns.unshift(node.object);
node = undefined;
} else {
node = undefined;
}
} while (node);
return ns;
}
/**
* Checks if the given identifier node is a ThisExpression in the global scope or the global window property.
* @param {Object} scope The current scope.
* @param {Object} globalScope The global scope.
* @param {string} node The identifier node to check
* @returns {boolean} Whether or not the node is a reference to the global object.
*/
function isGlobalThisReferenceOrGlobalWindow(scope, globalScope, node) {
if (scope.type === "global" && node.type === "ThisExpression") {
return true;
} else if (node.name === "window") {
return !isShadowed(scope, globalScope, node);
}
return false;
}
module.exports = {
getPropertyName,
findReference,
isShadowed,
isGlobalThisReferenceOrGlobalWindow,
buildMemberExpressionNamespace
};

Просмотреть файл

@ -0,0 +1,167 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
var util = require('../lib/util.js');
// This structure follows the same schema of the whitelisting mechanism from SES
// for ecma intrinsics, more details on ../lib/3rdparty/ses/whiteslit.js
var AuraAPI = {
$A: {
createComponent: true,
createComponents: true,
enqueueAction: true,
get: true,
getCallback: true,
getComponent: true,
getReference: true,
getRoot: true,
getToken: true,
log: true,
reportError: true,
toString: true,
warning: true,
util: {
addClass: true,
getBooleanValue: true,
hasClass: true,
isArray: true,
isEmpty: true,
isObject: true,
isUndefined: true,
isUndefinedOrNull: true,
removeClass: true,
toggleClass: true
},
localizationService: {
displayDuration: true,
displayDurationInDays: true,
displayDurationInHours: true,
displayDurationInMilliseconds: true,
displayDurationInMinutes: true,
displayDurationInMonths: true,
displayDurationInSeconds: true,
duration: true,
endOf: true,
formatCurrency: true,
formatDate: true,
formatDateTime: true,
formatDateTimeUTC: true,
formatDateUTC: true,
formatNumber: true,
formatPercent: true,
formatTime: true,
formatTimeUTC: true,
getDateStringBasedOnTimezone: true,
getDaysInDuration: true,
getDefaultCurrencyFormat: true,
getDefaultNumberFormat: true,
getDefaultPercentFormat: true,
getHoursInDuration: true,
getLocalizedDateTimeLabels: true,
getMillisecondsInDuration: true,
getMinutesInDuration: true,
getMonthsInDuration: true,
getNumberFormat: true,
getSecondsInDuration: true,
getToday: true,
getYearsInDuration: true,
isAfter: true,
isBefore: true,
isPeriodTimeView: true,
isSame: true,
parseDateTime: true,
parseDateTimeISO8601: true,
parseDateTimeUTC: true,
startOf: true,
toISOString: true,
translateFromLocalizedDigits: true,
translateFromOtherCalendar: true,
translateToLocalizedDigits: true,
translateToOtherCalendar: true,
UTCToWallTime: true,
WallTimeToUTC: true
}
}
};
module.exports = function(context) {
var globalScope;
return {
"Program": function() {
globalScope = context.getScope();
},
MemberExpression: function(node) {
if (node.parent.type === "MemberExpression") {
// ignoring intermediate member expressions
return;
}
var currentScope = context.getScope();
var ns = util.buildMemberExpressionNamespace(currentScope, globalScope, node);
if (ns.length > 0) {
var rootIdentifier = ns[0];
if (rootIdentifier.type !== "Identifier" || rootIdentifier.name !== "$A" || util.isShadowed(currentScope, globalScope, rootIdentifier)) {
return;
}
var api = AuraAPI;
for (var i = 0; i < ns.length; i++) {
var identifier = ns[i];
if (identifier.type !== 'Identifier') {
context.report(node, "Invalid Aura API, use dot notation instead");
return;
}
var token = identifier.name;
var nextIdentifier = ns[i + 1];
if (typeof api !== "object") {
context.report(node, "Invalid Aura API");
return;
}
if (!api.hasOwnProperty(token)) {
context.report(node, "Invalid Aura API");
return;
}
if (api[token] === '*') {
// anything from this point on is good
return;
}
if (typeof (api[token]) === 'object' && Object.keys(api[token]).length === 0) {
// nothing else to inspect
return;
}
if (api[token] === true && !nextIdentifier) {
// function call
return;
}
if (api[token] === true && nextIdentifier && nextIdentifier.type === 'Identifier' && (nextIdentifier.name === 'apply' || nextIdentifier.name === 'call')) {
// function call with .apply() or .call() are still valid
return;
}
if (api[token] === false && nextIdentifier === undefined) {
return;
}
api = api[token];
}
}
}
};
};
module.exports.schema = [];

Просмотреть файл

@ -0,0 +1,95 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
var util = require('../lib/util.js');
var intrinsics = require('../lib/3rdparty/ses/whitelist').whitelist;
var anonIntrinsics = intrinsics.cajaVM.anonIntrinsics;
module.exports = function(context) {
var globalScope;
return {
"Program": function() {
globalScope = context.getScope();
},
MemberExpression: function(node) {
if (node.parent.type === "MemberExpression") {
// ignoring intermediate member expressions
return;
}
var currentScope = context.getScope();
var ns = util.buildMemberExpressionNamespace(currentScope, globalScope, node);
if (ns.length > 0) {
var rootIdentifier = ns[0];
if (rootIdentifier.type !== "Identifier" || util.isShadowed(currentScope, globalScope, rootIdentifier)) {
return;
}
var api;
if (intrinsics.hasOwnProperty(rootIdentifier.name)) {
api = intrinsics;
} else if (anonIntrinsics.hasOwnProperty(rootIdentifier.name)) {
api = anonIntrinsics;
} else {
return; // nothing to do here, it is not intrinsic
}
for (var i = 0; i < ns.length; i++) {
var identifier = ns[i];
if (identifier.type !== 'Identifier') {
context.report(node, "Invalid Intrinsic API, use dot notation instead");
return;
}
var token = identifier.name;
var nextIdentifier = ns[i + 1];
if (typeof api !== "object") {
context.report(node, "Invalid Intrinsic API");
return;
}
if (!api || !Object.hasOwnProperty.call(api, token)) {
context.report(node, "Invalid Intrinsic API");
return;
}
if (api[token] === '*') {
// anything from this point on is good
return;
}
if (typeof (api[token]) === 'object' && Object.keys(api[token]).length === 0) {
// nothing else to inspect
return;
}
if (api[token] === true && !nextIdentifier) {
// function call
return;
}
if (api[token] === true && nextIdentifier && nextIdentifier.type === 'Identifier' && (nextIdentifier.name === 'apply' || nextIdentifier.name === 'call')) {
// function call with .apply() or .call() are still valid
return;
}
if (api[token] === false && nextIdentifier === undefined) {
return;
}
api = api[token];
}
}
}
};
};
module.exports.schema = [];

Просмотреть файл

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
// reference: http://eslint.org/docs/developer-guide/working-with-rules
"use strict";
module.exports = function(context) {
return {
// reference AST explorer (https://astexplorer.net/) when constructing your rule.
MyNewRule: function(node) {
// do something with node
context.report({
node: node,
message: "just for demonstration."
});
}
};
};
module.exports.schema = [];

Просмотреть файл

@ -0,0 +1,290 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
var util = require('../lib/util.js');
var objectAssign = require('object-assign');
// This structure follows the same schema of the whitelisting mechanism from SES
// for ecma intrinsics, more details on ../lib/3rdparty/ses/whiteslit.js
var SecureDocumentAPI = {
document: {
toString: true,
// HTMLDocument
location: '*',
fgColor: '*',
linkColor: '*',
vlinkColor: '*',
alinkColor: '*',
bgColor: '*',
clear: true,
captureEvents: true,
releaseEvents: true,
// Document
URL: '*',
activeElement: '*',
adoptNode: true,
anchors: '*',
applets: '*',
body: '*',
caretRangeFromPoint: true,
characterSet: '*',
charset: '*',
childElementCount: '*',
children: '*',
close: true,
compatMode: '*',
contentType: '*',
cookie: '*',
createAttribute: true,
createAttributeNS: true,
createCDATASection: true,
createComment: true,
createDocumentFragment: true,
createElement: true,
createElementNS: true,
createEvent: true,
createExpression: true,
createNSResolver: true,
createNodeIterator: true,
createProcessingInstruction: true,
createRange: true,
createTextNode: true,
createTreeWalker: true,
defaultView: '*',
designMode: '*',
dir: '*',
doctype: '*',
documentElement: '*',
documentURI: '*',
domain: '*',
elementFromPoint: true,
elementsFromPoint: true,
embeds: '*',
evaluate: true,
execCommand: true,
exitPointerLock: true,
firstElementChild: '*',
fonts: '*',
forms: '*',
getElementById: true,
getElementsByClassName: true,
getElementsByName: true,
getElementsByTagName: true,
getElementsByTagNameNS: true,
getSelection: true,
hasFocus: true,
head: '*',
hidden: '*',
images: '*',
implementation: '*',
importNode: true,
inputEncoding: '*',
lastElementChild: '*',
lastModified: '*',
links: '*',
onabort: true,
onautocomplete: true,
onautocompleteerror: true,
onbeforecopy: true,
onbeforecut: true,
onbeforepaste: true,
onblur: true,
oncancel: true,
oncanplay: true,
oncanplaythrough: true,
onchange: true,
onclick: true,
onclose: true,
oncontextmenu: true,
oncopy: true,
oncuechange: true,
oncut: true,
ondblclick: true,
ondrag: true,
ondragend: true,
ondragenter: true,
ondragleave: true,
ondragover: true,
ondragstart: true,
ondrop: true,
ondurationchange: true,
onemptied: true,
onended: true,
onerror: true,
onfocus: true,
oninput: true,
oninvalid: true,
onkeydown: true,
onkeypress: true,
onkeyup: true,
onload: true,
onloadeddata: true,
onloadedmetadata: true,
onloadstart: true,
onmousedown: true,
onmouseenter: true,
onmouseleave: true,
onmousemove: true,
onmouseout: true,
onmouseover: true,
onmouseup: true,
onmousewheel: true,
onpaste: true,
onpause: true,
onplay: true,
onplaying: true,
onpointerlockchange: true,
onpointerlockerror: true,
onprogress: true,
onratechange: true,
onreadystatechange: true,
onreset: true,
onresize: true,
onscroll: true,
onsearch: true,
onseeked: true,
onseeking: true,
onselect: true,
onselectionchange: true,
onselectstart: true,
onshow: true,
onstalled: true,
onsubmit: true,
onsuspend: true,
ontimeupdate: true,
ontoggle: true,
ontouchcancel: true,
ontouchend: true,
ontouchmove: true,
ontouchstart: true,
onvolumechange: true,
onwaiting: true,
onwebkitfullscreenchange: true,
onwebkitfullscreenerror: true,
onwheel: true,
open: true,
origin: '*',
plugins: '*',
pointerLockElement: '*',
preferredStylesheetSet: '*',
queryCommandEnabled: true,
queryCommandIndeterm: true,
queryCommandState: true,
queryCommandSupported: true,
queryCommandValue: true,
querySelector: true,
querySelectorAll: true,
readyState: '*',
referrer: '*',
registerElement: true,
rootElement: '*',
scripts: '*',
scrollingElement: '*',
selectedStylesheetSet: '*',
styleSheets: '*',
title: '*',
visibilityState: '*',
webkitCancelFullScreen: true,
webkitCurrentFullScreenElement: '*',
webkitExitFullscreen: true,
webkitFullscreenElement: '*',
webkitFullscreenEnabled: '*',
webkitHidden: '*',
webkitIsFullScreen: '*',
webkitVisibilityState: '*',
write: true,
writeln: true,
xmlEncoding: '*',
xmlStandalone: '*',
xmlVersion: '*'
}
};
objectAssign(SecureDocumentAPI.document, require('../lib/dom/element.js'));
objectAssign(SecureDocumentAPI.document, require('../lib/dom/global-event-handlers.js'));
objectAssign(SecureDocumentAPI.document, require('../lib/dom/event-target-methods.js'));
objectAssign(SecureDocumentAPI.document, require('../lib/dom/node.js'));
module.exports = function(context) {
var globalScope;
return {
"Program" : function() {
globalScope = context.getScope();
},
MemberExpression: function(node) {
if (node.parent.type === "MemberExpression") {
// ignoring intermediate member expressions
return;
}
var currentScope = context.getScope();
var ns = util.buildMemberExpressionNamespace(currentScope, globalScope, node);
if (ns.length > 0) {
var rootIdentifier = ns[0];
if (rootIdentifier.type !== "Identifier" || rootIdentifier.name !== "document" || util.isShadowed(currentScope, globalScope, rootIdentifier)) {
return;
}
var api = SecureDocumentAPI;
for (var i = 0; i < ns.length; i++) {
var identifier = ns[i];
if (identifier.type !== 'Identifier') {
context.report(node, "Invalid SecureDocument API, use dot notation instead");
return;
}
var token = identifier.name;
var nextIdentifier = ns[i + 1];
if (typeof api !== "object") {
context.report(node, "Invalid SecureDocument API");
return;
}
if (!api.hasOwnProperty(token)) {
context.report(node, "Invalid SecureDocument API");
return;
}
if (api[token] === '*') {
// anything from this point on is good
return;
}
if (typeof (api[token]) === 'object' && Object.keys(api[token]).length === 0) {
// nothing else to inspect
return;
}
if (api[token] === true && !nextIdentifier) {
// function call
return;
}
if (api[token] === true && nextIdentifier && nextIdentifier.type === 'Identifier' && (nextIdentifier.name === 'apply' || nextIdentifier.name === 'call')) {
// function call with .apply() or .call() are still valid
return;
}
if (api[token] === false && nextIdentifier === undefined) {
return;
}
api = api[token];
}
}
}
};
};
module.exports.schema = [];

Просмотреть файл

@ -0,0 +1,115 @@
/*
* Copyright (C) 2016 salesforce.com, inc.
*
* 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.
*/
"use strict";
var util = require('../lib/util.js');
var globalBlackList = {
setImmediate: true,
MutationEvent: true,
ServiceWorker: true,
ServiceWorkerContainer: true,
ServiceWorkerMessageEvent: true,
ServiceWorkerRegistration: true,
ShadowRoot: true,
SharedWorker: true,
WebKitMutationObserver: true,
clientInformation: true,
eval: true,
onwebkitanimationend: true,
onwebkitanimationiteration: true,
onwebkitanimationstart: true,
onwebkittransitionend: true,
opener: true,
top: true,
webkitAudioContext: true,
webkitCancelAnimationFrame: true,
webkitCancelRequestAnimationFrame: true,
webkitIDBCursor: true,
webkitIDBDatabase: true,
webkitIDBFactory: true,
webkitIDBIndex: true,
webkitIDBKeyRange: true,
webkitIDBObjectStore: true,
webkitIDBRequest: true,
webkitIDBTransaction: true,
webkitIndexedDB: true,
webkitMediaStream: true,
webkitOfflineAudioContext: true,
webkitRTCPeerConnection: true,
webkitRequestAnimationFrame: true,
webkitRequestFileSystem: true,
webkitResolveLocalFileSystemURL: true,
webkitSpeechGrammar: true,
webkitSpeechGrammarList: true,
webkitSpeechRecognition: true,
webkitSpeechRecognitionError: true,
webkitSpeechRecognitionEvent: true,
webkitStorageInfo: true,
webkitURL: true
};
module.exports = function(context) {
var globalScope;
return {
Program: function() {
globalScope = context.getScope();
},
CallExpression: function(node) {
var callee = node.callee,
currentScope = context.getScope();
if (callee.type === "Identifier") {
if (!util.isShadowed(currentScope, globalScope, callee)) {
if (globalBlackList[callee.name]) {
context.report(node, "Invalid SecureWindow API, " + callee.name + " was blacklisted");
}
}
}
},
MemberExpression: function(node) {
if (node.parent.type === "MemberExpression") {
// ignoring intermediate member expressions
return;
}
var currentScope = context.getScope();
var ns = util.buildMemberExpressionNamespace(currentScope, globalScope, node);
if (ns.length > 0) {
var rootIdentifier = ns[0];
var name = rootIdentifier.name;
if (rootIdentifier.type === "Literal") {
name = rootIdentifier.value;
}
if (util.isShadowed(currentScope, globalScope, rootIdentifier)) {
// nothing to do here, it was shadowed by the user
return;
}
if (globalBlackList[name]) {
context.report(node, "Invalid SecureWindow API, " + name + " was blacklisted");
return;
}
}
}
};
};
module.exports.schema = [];

Просмотреть файл

@ -0,0 +1,18 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es6",
"dom"
]
},
"include": [
".sfdx/tools/*.d.ts",
"**/*.js"
],
"exclude": [
"node_modules",
".vscode-test"
]
}

Просмотреть файл

@ -0,0 +1,688 @@
declare namespace $A {
/**
* Create a component from a type and a set of attributes.
* It accepts the name of a type of component, a map of attributes,
* and a callback to notify callers.
*/
export function createComponent(
type: string,
attributes: Object,
callback: (component: Component, status: any, errorMessage: any) => void): any;
/**
* Create an array of components from a list of types and attributes.
* It accepts a list of component names and attribute maps, and a callback
* to notify callers.
*/
export function createComponents(
type: Object[][],
attributes: Object,
callback: (component: Component[], status: any, errorMessage: any) => void): any;
/**
* This function must be called from within an event loop.
*/
export function enqueueAction(action: Action, background: boolean): any;
/**
* Returns the value referenced using property syntax. Gets the value from the specified global value provider
*/
export function get(key: string, callback: (any: any) => void): any;
/**
* Returns a callback which is safe to invoke from outside Aura, e.g. as an event handler or in a setTimeout.
* The $A.getCallback() call ensures that the framework rerenders the modified component
* and processes any enqueued actions.
*/
export function getCallback(callback: (any: any) => void): any;
/**
* Gets an instance of a component from either a GlobalId or a DOM element that was created via a Component Render.
*/
export function getComponent(idenfitier: Object): Component;
/**
* Gets the root component or application. For example, $A.getRoot().get("v.attrName"); returns the attribute from the root component.
*/
export function getRoot(): Component;
/**
* Logs to the browser's JavaScript console if it is available.
* This method doesn't log in PROD or PRODDEBUG modes.
* If both value and error are passed in, value shows up in the console as a group with value logged within the group.
* If only value is passed in, value is logged without grouping.
*/
export function log(value: Object, error: Object): any;
/**
* Report error to the server after handling it.
* Note that the method should only be used if try-catch mechanism
* of error handling is not desired or not functional (ex: in nested promises)
*/
export function reportError(message: string, error: Error): any;
/**
* Sets the value referenced using property syntax on the specified global value provider.
*/
export function set(key: string, value: Object): any;
/**
* $A.warning() should be used in the case where poor programming practices have been used.
*
* These warnings will not, in general, be displayed to the user, but they will appear in the console (if
* available), and in the aura debug window.
*/
export function warning(warning: string, error: Error): any;
/**
* Instance of the AuraLocalizationService which provides utility methods for localizing data or getting formatters for numbers, currencies, dates, etc.
*/
export const localizationService: AuraLocalizationService;
/**
* Collection of basic utility methods to operate on the DOM and Aura Components.
*/
export const util: Util;
}
interface AuraLocalizationService {
/**
* Converts a datetime from UTC to a specified timezone.
*/
UTCToWallTime(date: Date, timezone: string, callback: (any: any) => void): any;
/**
* Converts a datetime from a specified timezone to UTC.
*/
WallTimeToUTC(date: Date, timezone: string, callback: (any: any) => void): any;
/**
* Displays a length of time.
*/
displayDuration(d: Duration, noSuffix: boolean): string;
/**
* Displays a length of time in days.
*/
displayDurationInDays(d: Duration): number;
/**
* Displays a length of time in hours.
*/
displayDurationInHours(d: Duration): number;
/**
* Displays a length of time in milliseconds
*/
displayDurationInMilliseconds(d: Duration): number;
/**
*Displays a length of time in minutes.
*/
displayDurationInMinutes(d: Duration): number;
/**
* Displays a length of time in months.
*/
displayDurationInMonths(d: Duration): number;
/**
* Displays a length of time in seconds.
*/
displayDurationInSeconds(d: Duration): number;
/**
* Creates an Object representing a length of time.
*/
duration(num: number | Object, unit: string): Duration
/**
* Converts the passed in Date by setting it to the end of a unit of time.
*/
endOf(date: string | number | Date, unit: string): Date;
/**
* Returns a currency number based on the default currency format.
*/
formatCurrency(number: number): number
/**
* Formats a date.
*/
formatDate(date: string | number | Date, formatString: string, locale: string): string;
/**
* Formats a datetime.
*/
formatDateTime(date: string | number | Date, formatString: string, locale: string): string;
/**
* Formats a datetime in UTC.
*/
formatDateTimeUTC(date: string | number | Date, formatString: string, locale: string): string;
/**
* Formats a date in UTC.
*/
formatDateUTC(date: string | number | Date, formatString: string, locale: string): string;
/**
* Formats a number with the default number format.
*/
formatNumber(number: number): number;
/**
* Returns a formatted percentage number based on the default percentage format.
*/
formatPercent(number: number): number;
/**
* Formats a time.
*/
formatTime(date: string | number | Date, formatString: string, locale: string): string;
/**
* Formats a time in UTC.
*/
formatTimeUTC(date: string | number | Date, formatString: string, locale: string): string;
/**
* Get the date's date string based on a time zone.
*/
getDateStringBasedOnTimezone(timezone: string, date: Date, callback: (any: any) => void): string;
/**
* Gets the number of days in a duration.
*/
getDaysInDuration(d: Duration): number;
/**
* Returns the default currency format.
*/
getDefaultCurrencyFormat(): number;
/**
* Returns the default NumberFormat Object.
*/
getDefaultNumberFormat(): number;
/**
* Returns the default percentage Object.
*/
getDefaultPercentFormat(): number;
/**
* Get the number of hours in a duration.
*/
getHoursInDuration(d: Duration): number;
/**
* Get the date time related labels (month name, weekday name, am/pm etc.).
*/
getLocalizedDateTimeLabels(): Object;
/**
* Gets the number of milliseconds in a duration.
*/
getMillisecondsInDuration(d: Duration): number;
/**
* Gets the number of minutes in a duration.
*/
getMinutesInDuration(d: Duration): number;
/**
* Gets the number of months in a duration.
*/
getMonthsInDuration(d: Duration): number;
/**
* Returns a NumberFormat Object.
*/
getNumberFormat(format: string, symbols: string): number;
/**
* Gets the number of seconds in a duration.
*/
getSecondsInDuration(d: Duration): number;
/**
* Get today's date based on a time zone.
*/
getToday(timezone: string, callback: (any: any) => void): string;
/**
* Gets the number of years in a duration.
*/
getYearsInDuration(d: Duration): number;
/**
* Checks if date1 is after date2
*/
isAfter(date1: string | number | Date, date2: string | number | Date, unit: string): boolean;
/**
* Checks if date1 is before date2
*/
isBefore(date1: string | number | Date, date2: string | number | Date, unit: string): boolean;
/**
* A utility function to check if a datetime pattern string uses a 24-hour or period (12 hour with am/pm) time view.
*/
isPeriodTimeView(pattern: string): boolean;
/**
* Checks if date1 is same as date2
*/
isSame(date1: string | number | Date, date2: string | number | Date, unit: string): boolean;
/**
* Parses a string to a JavaScript Date.
*/
parseDateTime(dateTimeString: string, targetFormat: string, locale: string, strictParsing: boolean): Date;
/**
* Parses a date time string in an ISO-8601 format.
*/
parseDateTimeISO8601(dateTimeString: string): Date;
/**
* Parses a string to a JavaScript Date in UTC.
*/
parseDateTimeUTC(dateTimeString: string, targetFormat: string, locale: string, strictParsing: boolean): Date;
/**
* Converts the passed in Date by setting it to the start of a unit of time.
*/
startOf(date: string | number | Date, unit: string): Date;
/**
Most modern browsers support this method on Date Object. But that is not the case for IE8 and older.
*/
toISOString(date: Date): string;
/**
* Translate the localized digit string to a string with Arabic digits if there is any.
*/
translateFromLocalizedDigits(input: string): string;
/**
* Translate the input date from other calendar system (for example, Buddhist calendar) to Gregorian calendar based on the locale.
*/
translateFromOtherCalendar(date: Date): Date;
/**
* Translate the input string to a string with localized digits (different from Arabic) if there is any.
*/
translateToLocalizedDigits(input: string): string;
/**
* Translate the input date to a date in other calendar system, for example, Buddhist calendar based on the locale.
*/
translateToOtherCalendar(date: Date): Date;
}
type Duration = Object;
interface Action {
/**
* Returns an array of error Objects only for server-side actions.
* Each error Object has a message field.
* In any mode except PROD mode, each Object also has a stack field, which is a list
* describing the execution stack when the error occurred.
*/
getError(): Object[];
/**
* Gets an action parameter value for a parameter name.
*/
getParam(name: string): Object;
/**
* Gets the collection of parameters for this Action.
*/
getParams(): Object;
/**
* Gets the return value of the Action. A server-side Action can return any Object containing serializable JSON data.
*/
getReturnValue(): any;
/**
* Gets the current state of the Action. You should check the state of the action
* in the callback after the server-side action completes.
*/
getState(): string;
/**
* Returns true if the actions should be enqueued in the background, false if it should be run in the foreground.
*/
isBackground(): boolean
/**
* Set the action as abortable. Abortable actions are not sent to the server if the component is not valid.
* A component is automatically destroyed and marked invalid by the framework when it is unrendered.
*
* Actions not marked abortable are always sent to the server regardless of the validity of the component.
* For example, a save/modify action should not be set abortable to ensure it's always sent to the server
* even if the component is deleted.
*
* Setting an action as abortable cannot be undone
*/
setAbortable(): any;
/**
* Sets the action to run as a background action. This cannot be unset. Background actions are usually long running and
* lower priority actions. A background action is useful when you want your app to remain responsive to a user while it
* executes a low priority, long-running action. A rough guideline is to use a background action if it takes more than
* five seconds for the response to return from the server.
*/
setBackground(): any;
/**
* Sets the callback function that is executed after the server-side action returns. Call a server-side action from a
* client-side controller using <code>callback</code>.
*
* Note that you can register a callback for an explicit state, or you can use 'ALL' which registers callbacks for
* "SUCCESS", "ERROR", and "INCOMPLETE" (but not "ABORTED" for historical compatibility). It is recommended that you
* use an explicit name, and not the default 'undefined' to signify 'ALL'.
*
* The valid names are:
* * SUCCESS: if the action successfully completes.
* * ERROR: if the action has an error (including javascript errors for client side actions)
* * INCOMPLETE: if a server side action failed to complete because there is no connection
* * ABORTED: if the action is aborted via abort()
* * REFRESH: for server side storable actions, this will be called instead of the SUCCESS action when the storage is refreshed.
*/
setCallback(scope: Object, callback: (any: any) => void, name: string): any;
/**
* Sets a single parameter for the Action.
*/
setParam(key: string, value: Object): any;
/**
* Sets parameters for the Action.
*/
setParams(config: Object): any;
/**
* Marks the Action as storable. For server-side Actions only.
* Mark an action as storable to have its response stored in the client-side cache by the framework. Caching can be useful
* if you want your app to be functional for devices that temporarily dont have a network connection.
*/
setStorable(config: Object): any;
}
interface Component {
/**
* Adds an event handler. Resolving the handler Action happens at Event-handling
* time, so the Action reference may be altered at runtime, and that change is
* reflected in the handler.
*/
addHandler(eventName: string, valueProvider: Object, actionExpression: Object, insert: boolean, phase: string, includeFacets: boolean): any;
/**
* Adds handlers to Values owned by the Component.
*/
addValueHandler(config: Object): any;
/**
* Adds Custom ValueProviders to a component
*/
addValueProvider(key: string, valueProvider: Object): any;
/**
* Sets a flag to tell the rendering service whether or not to destroy this component when it is removed
* from its rendering facet. Set to false if you plan to keep a reference to a component after it has
* been unrendered or removed from a parent facet. Default is true: destroy once orphaned.
*/
autoDestroy(destroy: boolean): any;
/**
* Clears a live reference for the value indicated using property syntax.
* For example, if you use aura:set to set a value and later want to reset the value using <code>component.set()</code>,
* clear the reference before resetting the value.
*/
clearReference(key: string): any;
/**
* Destroys the component and cleans up memory.
* After a component that is declared in markup is no longer in use, the framework automatically destroys it
* and frees up its memory.
* If you create a component dynamically in JavaScript and that component isn't added to a facet (v.body or another
* attribute of type Aura.Component[]), you have to destroy it manually using destroy() to avoid memory leaks.
* destroy() destroys the component.
*/
destroy(sync: boolean): any;
/**
* Locates a component using the localId. Shorthand: get("asdf"),
* where "asdf" is the <code>aura:id</code> of the component to look for.
* Returns different types depending on the result.
* If the local ID is unique, find() returns the component.
* If there are multiple components with the same local ID, find() returns an array of the components.
* If there is no matching local ID, find() returns undefined.
* Returns instances of a component using the format
* cmp.find({ instancesOf : "auradocs:sampleComponent" }).
*/
find(name: string | Object): any;
/**
* Returns the value referenced using property syntax.
* For example, cmp.get("v.attr") returns the value of the attr aura:attribute.
*/
get(key: string): any;
/**
* Gets the concrete implementation of a component. If the component is
* concrete, the method returns the component itself. For example, call this
* method to get the concrete component of a super component.
*/
getConcreteComponent(): any;
/**
* If the component only rendered a single element, return it. Otherwise, you should use getElements().
*/
getElement(): any;
/**
* Returns a map of the elements previously rendered by this component.
*/
getElements(): any;
/**
* Returns a new event instance of the named component event.
*/
getEvent(name: string): any;
/**
* Gets the globalId. This is the generated globally unique id of the component. It can be used to locate the instance later, but will change across page loads.
*/
getGlobalId(): any;
/**
* Gets the id set using the aura:id attribute. Can be passed into find() on the parent to locate this child.
*/
getLocalId(): any;
/**
* Returns the component's canonical name, e.g. 'ui:button'.
*/
getName(): any;
/**
* Returns a live reference to the value indicated using property syntax. This is useful when you dynamically create a component.
*/
getReference(key: string): PropertyReferenceValue;
/**
* Returns the super component.
*/
getSuper(): Component;
/**
* Get the expected version number of a component based on its caller's requiredVersionDefs Note that for various rendering methods, we cannot rely on access stack. We use creation version instead.
*/
getVersion(): any;
/**
* Returns true if the component is concrete, or false otherwise.
*/
isConcrete(): boolean;
/**
* Checks whether the component is an instance of the given component name (or interface name).
*/
isInstanceOf(name: string): boolean;
/**
* Returns true if the component has not been destroyed.
*/
isValid(): any;
/**
* Sets the value referenced using property syntax.
*/
set(key: string, value: Object): any;
}
interface PropertyReferenceValue {
}
interface Event {
/**
* Fires the Event. Checks if the Event has already been fired before firing. Maps the component handlers to the event dispatcher
*/
fire(params: Object): any;
/**
* Gets the name of the Event.
*/
getName(): string;
/**
* Gets an Event parameter.
*/
getParam(name: string): string;
/**
* Gets all the Event parameters.
*/
getParams(): Object;
/**
* Gets the current phase of this event.
* Returns undefined if the event has not yet been fired.
* Possible return values for APPLICATION and COMPONENT events
* are "capture", "bubble", and "default" once fired.
* VALUE events return "default" once fired.
*/
getPhase(): any;
/**
* Gets the source component that fired this event.
*/
getSource(): Object;
/**
* Pauses this event such that event handlers will not be processed until
* Event.resume() is called. The handling process will pause in the current
* position of the event handler processing sequence. If the event is already
* paused, calling this does nothing. This will throw an error
* if called in the "default" phase.
*/
pause(): any;
/**
* Prevents the default phase execution for this event. This will throw
* an error if called in the "default" phase.
* The default is true.
*/
preventDefault(): any;
/**
* Resumes event handling for this event from the same position in the event
* handler processing sequence from which it was previously paused.
* If the event is not paused, calling this does nothing. This will throw an error
* if called in the "default" phase.
* This API does not define whether or not any remaining event handlers will
* execute in the current call stack or be deferred and executed in a new call stack,
* therefore the exact timing behavior is not dependable.
*/
resume(): any;
/**
* Sets a parameter for the Event. Does not modify an event that has already been fired.
*/
setParam(key: string, value: Object): any;
/**
* Sets parameters for the Event. Does not modify an event that has already been fired. Maps key in config to attributeDefs.
*/
setParams(config: Object): any;
/**
* Sets whether the event can bubble or not. This will throw an error if called in the "default" phase. The default is false.
*/
stopPropagation(): any;
}
interface Util {
/**
* Adds a CSS class to a component.
*/
addClass(element: Component, newClass: string): any;
/**
* Coerces truthy and falsy values into native booleans
*/
getBooleanValue(val: Object): boolean;
/**
* Checks whether the component has the specified CSS class.
*/
hasClass(element: Object, className: string): boolean;
/**
* Checks whether the specified Object is an array.
*/
isArray(obj: Object): boolean;
/**
* Checks if the Object is empty. An empty Object's value is undefined, null, an empty array, or empty string. An Object with no native properties is not considered empty.
*/
isEmpty(obj: Object): boolean;
/**
* Checks whether the specified Object is a valid Object. A valid Object: Is not a DOM element, is not a native browser class (XMLHttpRequest) is not falsey, and is not an array, error, function string or number
*/
isObject(obj: Object): boolean;
/**
* Checks if the Object is undefined.
*/
isUndefined(obj: Object): boolean;
/**
* Checks if the Object is undefined or null.
*/
isUndefinedOrNull(obj: Object): boolean;
/**
* Removes a CSS class from a component.
*/
removeClass(element: Object, newClass: string): any;
/**
* Toggles (adds or removes) a CSS class from a component.
*/
toggleClass(element: Object, className: string): any;
}

Просмотреть файл

@ -0,0 +1,7 @@
#!/bin/bash
JORJE_LOCATION=/Users/nchen/Development/IdeaProjects/apex-jorje
(cd $JORJE_LOCATION; mvn clean install -Plsp -DskipTests)
cp `find $JORJE_LOCATION -type f -name 'apex-jorje-lsp-*-SNAPSHOT.jar' -not -name 'apex-jorje-lsp-test-*-SNAPSHOT.jar'` dist/apex-jorje-lsp.jar

Просмотреть файл

@ -0,0 +1,189 @@
import * as vscode from 'vscode';
import * as child_process from 'child_process';
import * as path from 'path';
import * as status from './status';
let channel = vscode.window.createOutputChannel('Salesforce');
export function forceAuthWebLogin() {
channel.appendLine('force:auth:web:login');
status.showStatus('Authenticating');
child_process.exec(
`sfdx force:auth:web:login -d`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, 'force:auth:web:login');
status.hideStatus();
});
}
export function forceOrgCreate() {
channel.appendLine('force:org:create');
vscode.workspace.findFiles('config/*.json', '').then(files => {
let fileItems: vscode.QuickPickItem[] = files.map(file => {
return {
label: path.basename(file.toString()),
description: file.fsPath,
}
});
vscode.window.showQuickPick(fileItems).then(selection => {
if (selection) {
status.showStatus('Creating org');
let rootPath = vscode.workspace.rootPath!;
let selectionPath = path.relative(rootPath, selection.description.toString());
child_process.exec(
`sfdx force:org:create -f ${selectionPath} -s`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, 'force:org:create');
status.hideStatus();
});
}
});
});
}
export function forceOrgOpen() {
channel.appendLine('force:org:open');
status.showStatus('Opening org');
child_process.exec(
`sfdx force:org:open`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, 'force:org:open');
status.hideStatus();
});
}
export function forceSourcePull() {
channel.appendLine('force:source:pull');
status.showStatus('Pulling from org...');
child_process.exec(
`sfdx force:source:pull`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, `force:source:pull`);
status.hideStatus();
});
}
export function forceSourcePush() {
channel.appendLine('force:source:push');
status.showStatus('Pushing to org');
child_process.exec(
`sfdx force:source:push`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, `force:source:push`);
status.hideStatus();
});
}
export function forceSourceStatus() {
channel.appendLine('force:source:status');
status.showStatus('Checking status against org');
child_process.exec(
`sfdx force:source:status`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, `force:source:status`);
status.hideStatus();
});
}
export function forceApexTestRun(testClass?: string) {
channel.appendLine('force:apex:test:run');
if (testClass) {
status.showStatus('Running apex tests');
child_process.exec(
`sfdx force:apex:test:run -n ${testClass} -r human`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, 'force:apex:test:run');
status.hideStatus();
});
} else {
vscode.workspace.findFiles('**/*.testSuite-meta.xml', '').then(files => {
let fileItems: vscode.QuickPickItem[] = files.map(file => {
return {
label: path.basename(file.toString()).replace('.testSuite-meta.xml', ''),
description: file.fsPath,
}
});
fileItems.push({
label: 'All tests',
description: 'Runs all tests in the current workspace',
});
vscode.window.showQuickPick(fileItems).then(selection => {
if (selection) {
status.showStatus('Running apex tests');
if (selection.label === 'All tests') {
child_process.exec(
`sfdx force:apex:test:run -r human`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, 'force:apex:test:run');
status.hideStatus();
});
} else {
child_process.exec(
`sfdx force:apex:test:run -s ${selection.label} -r human`,
{
cwd: vscode.workspace.rootPath
},
(err, stdout, stderr) => {
genericOutputHandler(err, stdout, stderr, 'force:apex:test:run');
status.hideStatus();
});
}
}
});
});
}
}
function genericOutputHandler(err: Error, stdout: string, stderr: string, command: string) {
if (err) {
vscode.window.showErrorMessage(err.message);
}
channel.clear();
if (stdout) {
channel.append(stdout);
channel.show();
}
if (stderr) {
vscode.window.showErrorMessage(`Failed to execute${command}. Check the console for errors.`);
channel.append(stderr);
channel.show(true);
}
}

Просмотреть файл

@ -0,0 +1,103 @@
import * as vscode from 'vscode';
import * as child_process from 'child_process';
import * as path from 'path';
import * as net from 'net';
import * as portFinder from 'portfinder';
import * as requirements from './requirements';
import { LanguageClient, LanguageClientOptions, ServerOptions, StreamInfo } from 'vscode-languageclient';
const UBER_JAR_NAME = 'apex-jorje-lsp.jar';
const JDWP_DEBUG_PORT = 2739;
const APEX_LANGUAGE_SERVER_MAIN = 'apex.jorje.lsp.ApexLanguageServerLauncher';
declare var v8debug: any;
const DEBUG = (typeof v8debug === 'object') || startedInDebugMode();
async function createServer(context: vscode.ExtensionContext): Promise<StreamInfo> {
try {
let requirementsData = await requirements.resolveRequirements();
return new Promise<any>((resolve, reject) => {
portFinder.getPort((err, port) => {
let uberJar = path.resolve(context.extensionPath, 'dist', UBER_JAR_NAME);
let javaExecutable = path.resolve(`${requirementsData.java_home}/bin/java`);
let args: string[];
if (DEBUG) {
args = [
'-cp',
uberJar,
`-Dapex-lsp.port=${port}`,
'-Ddebug.internal.errors=true',
'-Ddebug.semantic.errors=false',
'-Dtrace.protocol=false',
`-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${JDWP_DEBUG_PORT}`,
APEX_LANGUAGE_SERVER_MAIN
];
} else {
args = [
'-cp',
uberJar,
`-Dapex-lsp.port=${port}`,
'-Ddebug.internal.errors=true',
'-Ddebug.semantic.errors=false',
APEX_LANGUAGE_SERVER_MAIN
]
}
net.createServer(socket => {
resolve({
reader: socket,
writer: socket
});
}).listen(port, () => {
let options = {
cwd: vscode.workspace.rootPath
};
let lspProcess = child_process.spawn(javaExecutable, args, options);
console.log('PROCESS INFO');
console.log(lspProcess);
lspProcess.stdout.on('data', (data) => {
console.log(`${data}`);
});
lspProcess.stderr.on('data', (data) => {
console.log(`${data}`);
});
lspProcess.on('close', (code) => {
console.log(`language server exited with code: ${code}`);
});
});
});
});
} catch (err) {
vscode.window.showErrorMessage(err);
throw err;
}
}
function startedInDebugMode(): boolean {
let args = (process as any).execArgv;
if (args) {
return args.some((arg: any) => /^--debug=?/.test(arg) || /^--debug-brk=?/.test(arg));
};
return false;
}
export function createLanguageServer(context: vscode.ExtensionContext): LanguageClient {
let clientOptions: LanguageClientOptions = {
// Register the server for Apex documents
documentSelector: ['apex'],
synchronize: {
configurationSection: 'apex',
fileEvents: [
vscode.workspace.createFileSystemWatcher('**/*.cls'), // Apex classes
vscode.workspace.createFileSystemWatcher('**/*.trigger'), // Apex triggers
vscode.workspace.createFileSystemWatcher('**/sfdx-project.json') // SFDX workspace configuration file
]
}
};
let client = new LanguageClient('apex', 'Apex Language Server', () => createServer(context), clientOptions);
return client;
}

Просмотреть файл

@ -0,0 +1,72 @@
// From https://github.com/redhat-developer/vscode-java
// Original version licensed under the Eclipse Public License (EPL)
import { workspace, Uri } from 'vscode';
import * as cp from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
const pathExists = require('path-exists');
const expandHomeDir = require('expand-home-dir');
const isWindows = process.platform.indexOf('win') === 0;
const JAVAC_FILENAME = 'javac' + (isWindows ? '.exe' : '');
interface RequirementsData {
java_home: string;
}
/**
* Resolves the requirements needed to run the extension.
* Returns a promise that will resolve to a RequirementsData if all requirements are resolved.
*
*/
export async function resolveRequirements(): Promise<RequirementsData> {
let java_home = await checkJavaRuntime();
await checkJavaVersion(java_home);
return Promise.resolve({ java_home: java_home }
);
}
function checkJavaRuntime(): Promise<any> {
return new Promise((resolve, reject) => {
let source: string;
let javaHome: string = readJavaConfig();
if (javaHome) {
source = 'The java.home variable defined in VS Code settings';
} else {
javaHome = process.env['JDK_HOME'];
if (javaHome) {
source = 'The JDK_HOME environment variable';
} else {
javaHome = process.env['JAVA_HOME'];
source = 'The JAVA_HOME environment variable';
}
}
if (javaHome) {
javaHome = expandHomeDir(javaHome);
if (!pathExists.sync(javaHome)) {
reject(`${source} points to a missing folder`);
}
return resolve(javaHome);
}
reject('Java runtime could not be located');
});
}
function readJavaConfig(): string {
const config = workspace.getConfiguration();
return config.get<string>('java.home', '');
}
function checkJavaVersion(java_home: string): Promise<any> {
return new Promise((resolve, reject) => {
cp.execFile(java_home + '/bin/java', ['-version'], {}, (error, stdout, stderr) => {
if (stderr.indexOf('1.8') < 0) {
reject('Java 8 is required to run. Please download and install a JRE.');
} else {
resolve(true);
}
});
});
}

Просмотреть файл

@ -0,0 +1,41 @@
import * as vscode from 'vscode';
import * as child_process from 'child_process';
import * as path from 'path';
import * as net from 'net';
import * as portFinder from 'portfinder';
import * as status from './status';
import * as scratchOrgDecorator from './scratch-org-decorator';
import * as commands from './commands';
import * as languageServer from './language-server';
import { LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, StreamInfo } from 'vscode-languageclient';
function registerCommands(): vscode.Disposable {
let forceAuthWebLoginCmd = vscode.commands.registerCommand('sfdx.force.auth.web.login', commands.forceAuthWebLogin);
let forceOrgCreateCmd = vscode.commands.registerCommand('sfdx.force.org.create', commands.forceOrgCreate);
let forceOrgOpenCmd = vscode.commands.registerCommand('sfdx.force.org.open', commands.forceOrgOpen);
let forceSourcePullCmd = vscode.commands.registerCommand('sfdx.force.source.pull', commands.forceSourcePull);
let forceSourcePushCmd = vscode.commands.registerCommand('sfdx.force.source.push', commands.forceSourcePush);
let forceSourceStatusCmd = vscode.commands.registerCommand('sfdx.force.source.status', commands.forceSourceStatus);
let forceApexTestRunCmd = vscode.commands.registerCommand('sfdx.force.apex.test.run', commands.forceApexTestRun);
return vscode.Disposable.from(
forceOrgCreateCmd,
forceOrgOpenCmd,
forceSourcePullCmd,
forceSourcePushCmd,
forceApexTestRunCmd
);
}
export function activate(context: vscode.ExtensionContext) {
console.log('Salesforce Extension Activated');
const commands = registerCommands();
const apexServer = languageServer.createLanguageServer(context).start();
context.subscriptions.push(commands);
context.subscriptions.push(apexServer);
scratchOrgDecorator.showOrg();
scratchOrgDecorator.monitorConfigChanges();
}
export function deactivate() {
console.log('Salesforce Extension Deactivated');
}

Просмотреть файл

@ -0,0 +1,34 @@
import { window, workspace, StatusBarItem, StatusBarAlignment } from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
const CONFIG_FILE = (path.join(workspace.rootPath!, '.sfdx/sfdx-config.json'));
let statusBarItem: StatusBarItem;
export function showOrg() {
if (!statusBarItem) {
statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 50);
statusBarItem.command= 'sfdx.force.org.open';
statusBarItem.show();
}
displayDefaultUserName(CONFIG_FILE);
}
export function monitorConfigChanges() {
let watcher = workspace.createFileSystemWatcher(CONFIG_FILE);
watcher.onDidChange(uri => {
displayDefaultUserName(uri.fsPath);
});
}
function displayDefaultUserName(configPath: string) {
fs.readFile(configPath, (err, data) => {
if (!err) {
const config = JSON.parse(data.toString());
if (config['defaultusername']) {
statusBarItem.text = `$(browser) ${config['defaultusername']}`;
}
}
});
}

Просмотреть файл

@ -0,0 +1,22 @@
import { window, StatusBarItem, StatusBarAlignment } from 'vscode';
let statusBarItem: StatusBarItem;
let statusTimer: NodeJS.Timer;
export function showStatus(status: string) {
if (!statusBarItem) {
statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, -10);
}
statusBarItem.text = `$(beaker) ${status}`;
statusTimer = setInterval(() => statusBarItem.text = statusBarItem.text + '.', 1000);
statusBarItem.show();
}
export function hideStatus() {
if (statusBarItem) {
statusBarItem.hide();
}
if (statusTimer) {
clearInterval(statusTimer);
}
}

Просмотреть файл

@ -0,0 +1,26 @@
{
"comments": {
"lineComment": "//",
"blockComment": [ "/*", "*/" ]
},
// symbols used as brackets
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
],
// symbols that are auto closed when typing
"autoClosingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["'", "'"]
],
// symbols that that can be used to surround a selection
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["'", "'"]
]
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,20 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"lib": [
"es6"
],
"sourceMap": true,
"moduleResolution": "node",
"noImplicitAny": true,
"rootDir": ".",
"outDir": "dist",
"preserveConstEnums": true,
"strictNullChecks": true
},
"exclude": [
"node_modules",
".vscode-test"
]
}