Skip to content

Commit

Permalink
✨ feat: Add module function checker
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed May 12, 2024
1 parent 66b7236 commit 9aaa50d
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2023-2024. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.sanitizer.checkers;


import com.caoccao.javet.sanitizer.options.JavetSanitizerOptions;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAst;
import com.caoccao.javet.swc4j.ast.module.*;
import com.caoccao.javet.swc4j.utils.SimpleSet;

import java.util.Set;

/**
* The type Base javet sanitizer module checker.
*
* @since 0.7.0
*/
public abstract class BaseJavetSanitizerModuleChecker extends BaseJavetSanitizerChecker {
/**
* The constant EXPORT_CLASSES.
*
* @since 0.7.0
*/
protected static final Set<Class<? extends ISwc4jAst>> EXPORT_CLASSES = SimpleSet.immutableOf(
Swc4jAstExportAll.class,
Swc4jAstExportDecl.class,
Swc4jAstExportDefaultDecl.class,
Swc4jAstExportDefaultExpr.class,
Swc4jAstNamedExport.class,
Swc4jAstTsExportAssignment.class,
Swc4jAstTsNamespaceExportDecl.class);
/**
* The constant IMPORT_CLASSES.
*
* @since 0.7.0
*/
protected static final Set<Class<? extends ISwc4jAst>> IMPORT_CLASSES = SimpleSet.immutableOf(
Swc4jAstImportDecl.class,
Swc4jAstTsImportEqualsDecl.class);

/**
* Instantiates a new Base javet sanitizer module checker.
*
* @since 0.7.0
*/
public BaseJavetSanitizerModuleChecker() {
this(JavetSanitizerOptions.Default);
}

/**
* Instantiates a new Base javet sanitizer module checker.
*
* @param options the options
* @since 0.7.0
*/
public BaseJavetSanitizerModuleChecker(JavetSanitizerOptions options) {
super(options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,13 @@
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAst;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstModuleDecl;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstStmt;
import com.caoccao.javet.swc4j.ast.module.*;
import com.caoccao.javet.swc4j.utils.SimpleSet;

import java.util.Set;

/**
* The type Javet sanitizer statement list checker.
*
* @since 0.7.0
*/
public class JavetSanitizerModuleChecker extends BaseJavetSanitizerChecker {
/**
* The constant EXPORT_CLASSES.
*
* @since 0.7.0
*/
protected static final Set<Class<? extends ISwc4jAst>> EXPORT_CLASSES = SimpleSet.immutableOf(
Swc4jAstExportAll.class,
Swc4jAstExportDecl.class,
Swc4jAstExportDefaultDecl.class,
Swc4jAstExportDefaultExpr.class,
Swc4jAstNamedExport.class,
Swc4jAstTsExportAssignment.class,
Swc4jAstTsNamespaceExportDecl.class);
/**
* The constant IMPORT_CLASSES.
*
* @since 0.7.0
*/
protected static final Set<Class<? extends ISwc4jAst>> IMPORT_CLASSES = SimpleSet.immutableOf(
Swc4jAstImportDecl.class,
Swc4jAstTsImportEqualsDecl.class);

public class JavetSanitizerModuleChecker extends BaseJavetSanitizerModuleChecker {
/**
* Instantiates a new Javet sanitizer statement list checker.
*
Expand Down Expand Up @@ -83,17 +57,21 @@ public void check(String codeString) throws JavetSanitizerException {
for (ISwc4jAst node : program.getBody()) {
if (node instanceof ISwc4jAstModuleDecl) {
if (!options.isKeywordExportEnabled() && EXPORT_CLASSES.contains(node.getClass())) {
validateNode(node, ISwc4jAstStmt.class);
checkNode(node);
}
if (!options.isKeywordImportEnabled() && IMPORT_CLASSES.contains(node.getClass())) {
validateNode(node, ISwc4jAstStmt.class);
checkNode(node);
}
} else {
validateNode(node, ISwc4jAstStmt.class);
checkNode(node);
}
}
}

protected void checkNode(ISwc4jAst node) throws JavetSanitizerException {
validateNode(node, ISwc4jAstStmt.class);
}

@Override
public String getName() {
return "Module";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2023-2024. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.sanitizer.checkers;


import com.caoccao.javet.sanitizer.exceptions.JavetSanitizerException;
import com.caoccao.javet.sanitizer.options.JavetSanitizerOptions;
import com.caoccao.javet.swc4j.ast.enums.Swc4jAstType;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAst;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstModuleDecl;
import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstFnDecl;

/**
* The type Javet sanitizer module function checker.
*
* @since 0.7.0
*/
public class JavetSanitizerModuleFunctionChecker extends BaseJavetSanitizerModuleChecker {
/**
* Instantiates a new Javet sanitizer module function checker.
*
* @since 0.7.0
*/
public JavetSanitizerModuleFunctionChecker() {
this(JavetSanitizerOptions.Default);
}

/**
* Instantiates a new Javet sanitizer module function checker.
*
* @param options the options
* @since 0.7.0
*/
public JavetSanitizerModuleFunctionChecker(JavetSanitizerOptions options) {
super(options);
}

@Override
public void check(String codeString) throws JavetSanitizerException {
super.check(codeString);
validateNoShebang(Swc4jAstType.getName(Swc4jAstFnDecl.class));
validateBodyNotEmpty();
for (ISwc4jAst node : program.getBody()) {
if (node instanceof ISwc4jAstModuleDecl) {
if (!options.isKeywordExportEnabled() && EXPORT_CLASSES.contains(node.getClass())) {
checkNode(node);
}
if (!options.isKeywordImportEnabled() && IMPORT_CLASSES.contains(node.getClass())) {
checkNode(node);
}
} else {
checkNode(node);
}
}
}

protected void checkNode(ISwc4jAst node) throws JavetSanitizerException {
validateNode(node, Swc4jAstFnDecl.class);
}

@Override
public String getName() {
return "Module Function";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2024. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.sanitizer.checkers;

import com.caoccao.javet.sanitizer.exceptions.JavetSanitizerError;
import com.caoccao.javet.sanitizer.exceptions.JavetSanitizerException;
import com.caoccao.javet.swc4j.utils.SimpleList;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

@SuppressWarnings("ThrowableNotThrown")
public class TestJavetSanitizerModuleFunctionChecker extends BaseTestSuiteCheckers {
@BeforeEach
public void beforeEach() {
checker = new JavetSanitizerModuleFunctionChecker();
}

@Test
public void testInvalidCases() {
SimpleList.of("", " ", null).forEach(code ->
assertException(
code,
JavetSanitizerError.EmptyCodeString,
JavetSanitizerError.EmptyCodeString.getFormat()));
assertException(
"import a from 'a'; a;",
JavetSanitizerError.KeywordNotAllowed,
"Keyword import is not allowed.\n" +
"Source: import a from 'a';\n" +
"Line: 1\n" +
"Column: 1\n" +
"Start: 0\n" +
"End: 18");
assertException(
"a; import b from 'b';",
JavetSanitizerError.KeywordNotAllowed,
"Keyword import is not allowed.\n" +
"Source: import b from 'b';\n" +
"Line: 1\n" +
"Column: 4\n" +
"Start: 3\n" +
"End: 21");
assertException(
"a; export const b = a;",
JavetSanitizerError.KeywordNotAllowed,
"Keyword export is not allowed.\n" +
"Source: export const b = a;\n" +
"Line: 1\n" +
"Column: 4\n" +
"Start: 3\n" +
"End: 22");
assertException(
"() => {}",
JavetSanitizerError.InvalidNode,
"Expression Statement is unexpected. Expecting Function Declaration in Module Function.\n" +
"Source: () => {}\n" +
"Line: 1\n" +
"Column: 1\n" +
"Start: 0\n" +
"End: 8");
assertException(
"const a = 0;",
JavetSanitizerError.InvalidNode,
"Var Declaration is unexpected. Expecting Function Declaration in Module Function.\n" +
"Source: const a = 0;\n" +
"Line: 1\n" +
"Column: 1\n" +
"Start: 0\n" +
"End: 12");
assertException(
"function a() {}\n() => {}",
JavetSanitizerError.InvalidNode,
"Expression Statement is unexpected. Expecting Function Declaration in Module Function.\n" +
"Source: () => {}\n" +
"Line: 2\n" +
"Column: 1\n" +
"Start: 16\n" +
"End: 24");
}

@Test
public void testValidCases() throws JavetSanitizerException {
List<String> statements = SimpleList.of(
"function a() {}", "function a(b, c) { return b + c; }",
"function a() {}\nfunction b() {}");
for (String statement : statements) {
checker.check(statement);
}
}
}

0 comments on commit 9aaa50d

Please sign in to comment.