Skip to content

Commit

Permalink
Add eslint as linter for javascript
Browse files Browse the repository at this point in the history
Closes #10
  • Loading branch information
priv-kweihmann committed Feb 22, 2019
1 parent 12fa32b commit c788dfc
Show file tree
Hide file tree
Showing 27 changed files with 760 additions and 12 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
recipes-foo/foo/acl_%.bbappend
recipes-foo/foo/core-image-minimal.bbappend
recipes-foo/foo/*
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ On the other hand some static code analysis does not make any sense on an image-

### Tools for image recipes

* pylint
* shellcheck
* pylint (python)
* shellcheck (shell)
* eslint (javascript/html)

### Tools for all other recipes

* pylint
* shellcheck
* pylint (python)
* shellcheck (shell)
* gcc (getting compiler warnings/errors)
* cpplint
* cppcheck
* cpplint (c/c++)
* cppcheck (c/c++)
* eslint (javascript/html)

each tool does have it's own benefits and flaws so don't be mad if you have 10k+ findings on the initial run.

Expand Down Expand Up @@ -122,6 +124,13 @@ For further explanations on the variables see the manpage of cppcheck
| SCA_SHELLCHECK_EXTRA_SUPPRESS | Extra error-ids to be suppressed | space-separated-list | ""
| SCA_SHELLCHECK_EXTRA_FATAL | Extra error-ids leading to build termination when found | space-separated-list | "":

### Available configuration for eslint
| var | purpose | type | default |
| ------------- |:-------------:| -----:| -----:
| SCA_ESLINT_EXTRA_SUPPRESS | Extra error-ids to be suppressed | space-separated-list | ""
| SCA_ESLINT_EXTRA_FATAL | Extra error-ids leading to build termination when found | space-separated-list | "":
| SCA_ESLINT_CONFIG_FILE | Configuration-file to be used. See recipe eslint-native for details | string: eslint-standard.json, eslint-plain.json, eslint-airbnb.json, eslint-google.json | eslint-plain.json

## Suppression and fatal-error
Every tool has the possibility to suppress some of the findings.
Besides that some findings could be configured to terminate the build, e.g. when a nullptr-dereference is found in C-code.
Expand Down
33 changes: 33 additions & 0 deletions classes/sca-conv-checkstyle-eslint.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## This file contains the converter from raw
## cppcheck-format to checkstyle

inherit sca-conv-checkstyle-helper

def do_sca_conv_eslint(d):
import os
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.etree import ElementTree
from xml.dom import minidom

package_name = d.getVar("PN", True)
buildpath = d.getVar("SCA_SOURCES_DIR", True)

try:
data = ElementTree.ElementTree(ElementTree.parse(d.getVar("SCA_RAW_RESULT"))).getroot()
items = []

for f in data.findall(".//error"):
if ElementTree.tostring(f) in items or f.attrib["severity"] not in checkstyle_allowed_warning_level(d):
for h in f:
f.remove(h)
continue
items.append(ElementTree.tostring(f))
data = data.getroot()
except Exception as e:
data = Element("checkstyle")
data.set("version", "4.3")

try:
return checkstyle_prettify(d, data).decode("utf-8")
except:
return checkstyle_prettify(d, data)
2 changes: 1 addition & 1 deletion classes/sca-conv-checkstyle-shellcheck.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def do_sca_conv_shellcheck(d):
data = ElementTree.ElementTree(ElementTree.parse(d.getVar("SCA_RAW_RESULT"))).getroot()
items = []

for f in data.findall(".//file"):
for f in data.findall(".//error"):
if ElementTree.tostring(f) in items or f.attrib["severity"] not in checkstyle_allowed_warning_level(d):
for h in f:
f.remove(h)
Expand Down
74 changes: 74 additions & 0 deletions classes/sca-eslint-core.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
inherit sca-conv-checkstyle-eslint
inherit sca-license-filter

## Set the config file to be used - the files must be placed at ${STAGING_DATADIR_NATIVE}/eslint/configs
## See eslint-native recipe for details
SCA_ESLINT_CONFIG_FILE ?= "eslint-plain.json"
SCA_ESLINT_EXTRA_SUPPRESS ?= ""
SCA_ESLINT_EXTRA_FATAL ?= ""

python do_prepare_recipe_sysroot_append() {
import glob
import os

## Rewrite all of the packages-paths if we have to
for item in glob.glob(os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint") + "/**/package.json", recursive=True):
content = ""
with open(item, "r") as i:
content = i.read().replace("%SYSROOT%", d.getVar("STAGING_DATADIR_NATIVE"))
with open(item, "w") as o:
o.write(content)
}

DEPENDS += "nodejs-native eslint-native"

python do_sca_eslint_core() {
import os
import subprocess
import json

d.setVar("SCA_EXTRA_SUPPRESS", d.getVar("SCA_ESLINT_EXTRA_SUPPRESS"))
d.setVar("SCA_EXTRA_FATAL", d.getVar("SCA_ESLINT_EXTRA_FATAL"))
d.setVar("SCA_SUPRESS_FILE", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint-suppress"))
d.setVar("SCA_FATAL_FILE", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint-fatal"))

_supress = get_suppress_entries(d)
_fatal = get_fatal_entries(d)

_args = [os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint", "node_modules", ".bin", "eslint")]
_args += ["-c", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint", "configs", d.getVar("SCA_ESLINT_CONFIG_FILE"))]
_args += ["-f", "checkstyle"]
_args += ["--quiet"]
_args += [d.getVar("SCA_SOURCES_DIR") + "/"]

cmd_output = ""
try:
cmd_output = subprocess.check_output(_args, universal_newlines=True)
except subprocess.CalledProcessError as e:
cmd_output = e.stdout or ""
result_raw_file = os.path.join(d.getVar("T"), "sca_raw_eslint.xml")
d.setVar("SCA_RAW_RESULT", result_raw_file)
with open(result_raw_file, "w") as o:
o.write(cmd_output)
xml_output = do_sca_conv_eslint(d)
result_file = os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml")
d.setVar("SCA_RESULT_FILE", result_file)
with open(result_file, "w") as o:
o.write(xml_output)

## Evaluate
_warnings = get_warnings_from_result(d)
_fatals = get_fatal_from_result(d, "eslint.", _fatal)
_errors = get_errors_from_result(d)

warn_log = []
if any(_warnings):
warn_log.append("{} warning(s)".format(len(_warnings)))
if any(_errors):
warn_log.append("{} error(s)".format(len(_errors)))
if warn_log:
bb.warn("SCA has found {}".format(",".join(warn_log)))

if any(_fatals):
bb.fatal("SCA has following fatal errors: {}".format("\n".join(_fatals)))
}
46 changes: 46 additions & 0 deletions classes/sca-eslint-image.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
inherit sca-helper
inherit sca-global
inherit sca-eslint-core
inherit sca-conv-checkstyle-helper

python do_sca_deploy_eslint_image() {
import os
import shutil

os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw"), exist_ok=True)
os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle"), exist_ok=True)

import os
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.etree import ElementTree
from xml.dom import minidom

for _file in ["sca_raw_eslint.xml", "sca_checkstyle_eslint.xml"]:
if not os.path.exists(os.path.join(d.getVar("T"), _file)):
continue
data = ElementTree.parse(os.path.join(d.getVar("T"), _file)).getroot()
for node in data.findall(".//error"):
## Patch to common format
node.attrib["message"] = "[Package:'{}' Tool:eslint] {}".format(d.getVar("PN"), node.attrib["message"])
node.attrib["source"] = "ShellCheck.{}".format(node.attrib["source"])

res = ""
try:
res = checkstyle_prettify(d, data).decode("utf-8")
except:
res = checkstyle_prettify(d, data)
with open(os.path.join(d.getVar("T"), _file), "w") as f:
f.write(res)

raw_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV")))
cs_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV")))
shutil.copy(os.path.join(d.getVar("T"), "sca_raw_eslint.xml"), raw_target)
shutil.copy(os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml"), cs_target)

do_sca_export_sources(d, cs_target)
}

addtask do_sca_eslint_core before before do_image_complete after do_image
addtask do_sca_deploy_eslint_image before do_image_complete after do_sca_eslint_core

DEPENDS += "sca-image-eslint-rules-native"
48 changes: 48 additions & 0 deletions classes/sca-eslint-recipe.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
inherit sca-helper
inherit sca-global
inherit sca-eslint-core

python do_sca_deploy_eslint_recipe() {
import os
import shutil

os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw"), exist_ok=True)
os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle"), exist_ok=True)

import os
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.etree import ElementTree
from xml.dom import minidom

for _file in ["sca_raw_eslint.xml", "sca_checkstyle_eslint.xml"]:
try:
data = ElementTree.parse(os.path.join(d.getVar("T"), _file)).getroot()
for node in data.findall(".//error"):
## Patch to common format
node.attrib["message"] = "[Package:'{}' Tool:eslint] {}".format(d.getVar("PN"), node.attrib["message"])
node.attrib["source"] = "eslint.{}".format(node.attrib["source"])

res = ""
try:
res = prettify(top).decode("utf-8")
except:
res = prettify(top)
with open(os.path.join(d.getVar("T"), _file), "w") as f:
f.write(res)
except:
pass

raw_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV")))
cs_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV")))
if os.path.exists(os.path.join(d.getVar("T"), "sca_raw_eslint.xml")):
shutil.copy(os.path.join(d.getVar("T"), "sca_raw_eslint.xml"), raw_target)
if os.path.exists(os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml")):
shutil.copy(os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml"), cs_target)

do_sca_export_sources(d, cs_target)
}

addtask do_sca_eslint_core before do_install after do_compile
addtask do_sca_deploy_eslint_recipe before do_package after do_sca_eslint_core

DEPENDS += "sca-recipe-eslint-rules-native"
2 changes: 1 addition & 1 deletion classes/sca-license-filter.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def sca_filter_by_license_image(d, licenses):
return list(set(ignores))

def sca_filter_by_license_recipe(d, licenses):
if d.getVar("LICENSE") in licenses:
if not d.getVar("LICENSE") in licenses:
return []
return [ 1 ] ## return dummy value

Expand Down
2 changes: 1 addition & 1 deletion classes/sca-on-image.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
inherit sca-global

SCA_PACKAGE_LICENSE_FILTER = "CLOSED"
SCA_ENABLED_MODULES ?= "shellcheck pylint"
SCA_ENABLED_MODULES ?= "eslint pylint shellcheck"
SCA_SOURCES_DIR ?= "${IMAGE_ROOTFS}"

SCA_MODE = "image"
Expand Down
2 changes: 1 addition & 1 deletion classes/sca-on-recipe.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
inherit sca-global
inherit sca-license-filter

SCA_ENABLED_MODULES ?= "gcc cpplint cppcheck pylint shellcheck"
SCA_ENABLED_MODULES ?= "eslint cpplint cppcheck gcc pylint shellcheck"
SCA_SOURCES_DIR ?= "${B}"

SCA_MODE = "recipe"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
From c2aff16cc196a61f4ab1cdae4a91c7926123c239 Mon Sep 17 00:00:00 2001
From: Zuzana Svetlikova <[email protected]>
Date: Thu, 27 Apr 2017 14:25:42 +0200
Subject: [PATCH] Disable running gyp on shared deps

---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index a98772f..f5663e2 100644
--- a/Makefile
+++ b/Makefile
@@ -123,8 +123,8 @@ with-code-cache:
test-code-cache: with-code-cache
$(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) code-cache

-out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp \
- deps/zlib/zlib.gyp deps/v8/gypfiles/toolchain.gypi \
+out/Makefile: common.gypi deps/http_parser/http_parser.gyp \
+ deps/v8/gypfiles/toolchain.gypi \
deps/v8/gypfiles/features.gypi deps/v8/gypfiles/v8.gyp node.gyp \
config.gypi
$(PYTHON) tools/gyp_node.py -f make
--
2.19.2
36 changes: 36 additions & 0 deletions recipes-devtools/nodejs/nodejs/0002-Using-native-torque.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
From 4bbee5e3d58bc4911999f3ec2cc5aab8ded6717b Mon Sep 17 00:00:00 2001
From: "Winker Matthias (TT-CA/ENG1)" <[email protected]>
Date: Tue, 11 Dec 2018 10:44:29 +0100
Subject: [PATCH] Using native torque

---
deps/v8/gypfiles/v8.gyp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/deps/v8/gypfiles/v8.gyp b/deps/v8/gypfiles/v8.gyp
index 8c78f02255..434168844e 100644
--- a/deps/v8/gypfiles/v8.gyp
+++ b/deps/v8/gypfiles/v8.gyp
@@ -2831,7 +2831,6 @@
{
'action_name': 'run_torque',
'inputs': [ # Order matters.
- '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)torque<(EXECUTABLE_SUFFIX)',
'../src/builtins/base.tq',
'../src/builtins/array.tq',
'../src/builtins/typed-array.tq',
@@ -2845,7 +2844,10 @@
'<(SHARED_INTERMEDIATE_DIR)/torque-generated/builtins-typed-array-from-dsl-gen.cc',
'<(SHARED_INTERMEDIATE_DIR)/torque-generated/builtins-typed-array-from-dsl-gen.h',
],
- 'action': ['<@(_inputs)', '-o', '<(SHARED_INTERMEDIATE_DIR)/torque-generated'],
+ 'action': [
+ 'torque',
+ '<@(_inputs)',
+ '-o', '<(SHARED_INTERMEDIATE_DIR)/torque-generated'],
},
],
}, # torque
--
2.19.2

Loading

0 comments on commit c788dfc

Please sign in to comment.