Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature js in smell #312

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions spec/SmellSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -503,5 +503,17 @@ spec = do
describe "usesVarInsteadOfLet" $ do
it "is True when there is a var" $ do
usesVarInsteadOfLet (js "var x = 1; x++") `shouldBe` True

it "is False when there is no var" $ do
usesVarInsteadOfLet (js "let x = 1; x++") `shouldBe` False
usesVarInsteadOfLet (js "const x = 1; x++") `shouldBe` False

describe "usesForInInsteadOfForOf" $ do
it "is True when there is a for..in" $ do
usesForInInsteadOfForOf (js "for (let x in []) {}") `shouldBe` True
usesForInInsteadOfForOf (js "for (var x in []) {}") `shouldBe` True

it "is False when there is no for..in" $ do
usesForInInsteadOfForOf (js "for (var x of []) {}") `shouldBe` False
usesForInInsteadOfForOf (js "for (let x of []) {}") `shouldBe` False
usesForInInsteadOfForOf (js "for (const x of []) {}") `shouldBe` False
90 changes: 46 additions & 44 deletions src/Language/Mulang/Analyzer/SmellsAnalyzer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ allSmells = [
"UsesFail",
"UsesNamedSelfReference",
"UsesUnificationOperator",
"JavaScript#UsesVarInsteadOfLet" ]
"JavaScript#UsesVarInsteadOfLet",
"JavaScript#UsesForInInsteadOfForOf" ]

---
--- Instantiation
Expand Down Expand Up @@ -131,49 +132,50 @@ evalSmellInstance :: SmellsContext -> Expression -> SmellInstance -> [Expectatio
evalSmellInstance context expression smellInstance = map (expectationFor smellInstance) . detectionFor smellInstance context $ expression

detectionFor :: SmellInstance -> Detection
detectionFor ("DiscardsExceptions", Nothing) = simple discardsExceptions
detectionFor ("DoesConsolePrint", Nothing) = simple doesConsolePrint
detectionFor ("DoesNilTest", Nothing) = simple doesNilTest
detectionFor ("DoesNullTest", Nothing) = simple doesNilTest
detectionFor ("DoesTypeTest", Nothing) = simple doesTypeTest
detectionFor ("HasAssignmentCondition", Nothing) = simple hasAssignmentCondition
detectionFor ("HasAssignmentReturn", Nothing) = simple hasAssignmentReturn
detectionFor ("HasCodeDuplication", Nothing) = unsupported
detectionFor ("HasDeclarationTypos", Just target) = raw (detectDeclarationTypos target)
detectionFor ("HasEmptyIfBranches", Nothing) = simple hasEmptyIfBranches
detectionFor ("HasEmptyRepeat", Nothing) = simple hasEmptyRepeat
detectionFor ("HasEqualIfBranches", Nothing) = simple hasEqualIfBranches
detectionFor ("HasLongParameterList", Nothing) = simple hasLongParameterList
detectionFor ("HasMisspelledBindings", Nothing) = withLanguage hasMisspelledIdentifiers
detectionFor ("HasMisspelledIdentifiers", Nothing) = withLanguage hasMisspelledIdentifiers
detectionFor ("HasRedundantBooleanComparison", Nothing) = simple hasRedundantBooleanComparison
detectionFor ("HasRedundantGuards", Nothing) = simple hasRedundantGuards
detectionFor ("HasRedundantIf", Nothing) = simple hasRedundantIf
detectionFor ("HasRedundantLambda", Nothing) = simple hasRedundantLambda
detectionFor ("HasRedundantLocalVariableReturn", Nothing) = simple hasRedundantLocalVariableReturn
detectionFor ("HasRedundantParameter", Nothing) = simple hasRedundantParameter
detectionFor ("HasRedundantReduction", Nothing) = simple hasRedundantReduction
detectionFor ("HasRedundantRepeat", Nothing) = simple hasRedundantRepeat
detectionFor ("HasTooManyMethods", Nothing) = simple hasTooManyMethods
detectionFor ("HasTooShortBindings", Nothing) = withLanguage hasTooShortIdentifiers
detectionFor ("HasTooShortIdentifiers", Nothing) = withLanguage hasTooShortIdentifiers
detectionFor ("HasUnreachableCode", Nothing) = simple hasUnreachableCode
detectionFor ("HasUsageTypos", Just target) = raw (detectUsageTypos target)
detectionFor ("HasWrongCaseBinding", Nothing) = withLanguage hasWrongCaseIdentifiers
detectionFor ("HasWrongCaseIdentifiers", Nothing) = withLanguage hasWrongCaseIdentifiers
detectionFor ("IsLongCode", Nothing) = unsupported
detectionFor ("OverridesEqualOrHashButNotBoth", Nothing) = simple overridesEqualOrHashButNotBoth
detectionFor ("ReturnsNil", Nothing) = simple returnsNil
detectionFor ("ReturnsNull", Nothing) = simple returnsNil
detectionFor ("ShouldInvertIfCondition", Nothing) = simple shouldInvertIfCondition
detectionFor ("ShouldUseOtherwise", Nothing) = simple shouldUseOtherwise
detectionFor ("ShouldUseStrictComparators", Nothing) = simple shouldUseStrictComparators
detectionFor ("UsesCut", Nothing) = simple usesCut
detectionFor ("UsesFail", Nothing) = simple usesFail
detectionFor ("UsesNamedSelfReference", Nothing) = simple usesNamedSelfReference
detectionFor ("UsesUnificationOperator", Nothing) = simple usesUnificationOperator
detectionFor ("JavaScript#UsesVarInsteadOfLet", Nothing) = simple usesVarInsteadOfLet
detectionFor _ = unsupported
detectionFor ("DiscardsExceptions", Nothing) = simple discardsExceptions
detectionFor ("DoesConsolePrint", Nothing) = simple doesConsolePrint
detectionFor ("DoesNilTest", Nothing) = simple doesNilTest
detectionFor ("DoesNullTest", Nothing) = simple doesNilTest
detectionFor ("DoesTypeTest", Nothing) = simple doesTypeTest
detectionFor ("HasAssignmentCondition", Nothing) = simple hasAssignmentCondition
detectionFor ("HasAssignmentReturn", Nothing) = simple hasAssignmentReturn
detectionFor ("HasCodeDuplication", Nothing) = unsupported
detectionFor ("HasDeclarationTypos", Just target) = raw (detectDeclarationTypos target)
detectionFor ("HasEmptyIfBranches", Nothing) = simple hasEmptyIfBranches
detectionFor ("HasEmptyRepeat", Nothing) = simple hasEmptyRepeat
detectionFor ("HasEqualIfBranches", Nothing) = simple hasEqualIfBranches
detectionFor ("HasLongParameterList", Nothing) = simple hasLongParameterList
detectionFor ("HasMisspelledBindings", Nothing) = withLanguage hasMisspelledIdentifiers
detectionFor ("HasMisspelledIdentifiers", Nothing) = withLanguage hasMisspelledIdentifiers
detectionFor ("HasRedundantBooleanComparison", Nothing) = simple hasRedundantBooleanComparison
detectionFor ("HasRedundantGuards", Nothing) = simple hasRedundantGuards
detectionFor ("HasRedundantIf", Nothing) = simple hasRedundantIf
detectionFor ("HasRedundantLambda", Nothing) = simple hasRedundantLambda
detectionFor ("HasRedundantLocalVariableReturn", Nothing) = simple hasRedundantLocalVariableReturn
detectionFor ("HasRedundantParameter", Nothing) = simple hasRedundantParameter
detectionFor ("HasRedundantReduction", Nothing) = simple hasRedundantReduction
detectionFor ("HasRedundantRepeat", Nothing) = simple hasRedundantRepeat
detectionFor ("HasTooManyMethods", Nothing) = simple hasTooManyMethods
detectionFor ("HasTooShortBindings", Nothing) = withLanguage hasTooShortIdentifiers
detectionFor ("HasTooShortIdentifiers", Nothing) = withLanguage hasTooShortIdentifiers
detectionFor ("HasUnreachableCode", Nothing) = simple hasUnreachableCode
detectionFor ("HasUsageTypos", Just target) = raw (detectUsageTypos target)
detectionFor ("HasWrongCaseBinding", Nothing) = withLanguage hasWrongCaseIdentifiers
detectionFor ("HasWrongCaseIdentifiers", Nothing) = withLanguage hasWrongCaseIdentifiers
detectionFor ("IsLongCode", Nothing) = unsupported
detectionFor ("OverridesEqualOrHashButNotBoth", Nothing) = simple overridesEqualOrHashButNotBoth
detectionFor ("ReturnsNil", Nothing) = simple returnsNil
detectionFor ("ReturnsNull", Nothing) = simple returnsNil
detectionFor ("ShouldInvertIfCondition", Nothing) = simple shouldInvertIfCondition
detectionFor ("ShouldUseOtherwise", Nothing) = simple shouldUseOtherwise
detectionFor ("ShouldUseStrictComparators", Nothing) = simple shouldUseStrictComparators
detectionFor ("UsesCut", Nothing) = simple usesCut
detectionFor ("UsesFail", Nothing) = simple usesFail
detectionFor ("UsesNamedSelfReference", Nothing) = simple usesNamedSelfReference
detectionFor ("UsesUnificationOperator", Nothing) = simple usesUnificationOperator
detectionFor ("JavaScript#UsesVarInsteadOfLet", Nothing) = simple usesVarInsteadOfLet
detectionFor ("JavaScript#UsesForInInsteadOfForOf", Nothing) = simple usesForInInsteadOfForOf
detectionFor _ = unsupported

unsupported :: Detection
unsupported _ _ = []
Expand Down
8 changes: 7 additions & 1 deletion src/Language/Mulang/Inspector/Smell/JavaScript.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Language.Mulang.Inspector.Smell.JavaScript (
usesVarInsteadOfLet) where
usesVarInsteadOfLet,
usesForInInsteadOfForOf) where

import Language.Mulang.Ast
import Language.Mulang.Inspector.Primitive (Inspection, containsExpression)
Expand All @@ -10,3 +11,8 @@ usesVarInsteadOfLet = containsExpression f
where f (Other (Just "JSVar") _) = True
f (For [Generator (OtherPattern (Just "JSVar") _) _] _) = True
f _ = False

usesForInInsteadOfForOf :: Inspection
usesForInInsteadOfForOf = containsExpression f
where f (Other (Just "JSForIn") _) = True
f _ = False
11 changes: 8 additions & 3 deletions src/Language/Mulang/Parsers/JavaScript.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,20 @@ muJSAST (JSAstStatement statement _) = muJSStatement statement
muJSAST (JSAstExpression expression _) = muJSExpression expression
muJSAST (JSAstLiteral expression _) = muJSExpression expression


muJSStatement:: JSStatement -> Expression
muJSStatement (JSStatementBlock _ statements _ _) = compactMap muJSStatement statements
--muJSStatement (JSConstant _ (JSCommaList JSExpression) _) -- ^const, decl, autosemi
muJSStatement (JSDoWhile _ statement _ _ expression _ _) = While (muJSExpression expression) (muJSStatement statement)
muJSStatement (JSForLetIn _ _ _ (JSVarInitExpression id _) _ gen _ body) = muForIn VariablePattern id gen body
muJSStatement (JSForIn _ _ id _ gen _ body) = muForIn muJsVarPattern id gen body
muJSStatement (JSForVarIn _ _ _ (JSVarInitExpression id _) _ gen _ body) = muForIn muJsVarPattern id gen body
muJSStatement (JSFor _ _ inits _ conds _ progs _ body) = muFor inits conds progs body
muJSStatement (JSForVar _ _ _ inits _ conds _ progs _ body) = muFor inits conds progs body
muJSStatement (JSForLet _ _ _ inits _ conds _ progs _ body) = muFor inits conds progs body
muJSStatement (JSForConstOf _ _ _ (JSVarInitExpression id _) _ gen _ body) = muForOf ConstantPattern id gen body
muJSStatement (JSForLetOf _ _ _ (JSVarInitExpression id _) _ gen _ body) = muForOf VariablePattern id gen body
muJSStatement (JSForOf _ _ id _ gen _ body) = muForOf (otherPattern "JSVar" . VariablePattern) id gen body
muJSStatement (JSForVarOf _ _ _ (JSVarInitExpression id _) _ gen _ body) = muForOf (otherPattern "JSVar" . VariablePattern) id gen body
muJSStatement (JSForOf _ _ id _ gen _ body) = muForOf muJsVarPattern id gen body
muJSStatement (JSForVarOf _ _ _ (JSVarInitExpression id _) _ gen _ body) = muForOf muJsVarPattern id gen body
muJSStatement (JSFunction _ ident _ params _ body _) = muComputation ident params body
muJSStatement (JSIf _ _ expression _ statement) = If (muJSExpression expression) (muJSStatement statement) None
muJSStatement (JSIfElse _ _ expression _ ifStatement _ elseStatement) = If (muJSExpression expression) (muJSStatement ifStatement) (muJSStatement elseStatement)
Expand Down Expand Up @@ -97,6 +99,8 @@ muJSPatternList = mapJSList muExpressionPattern

muJSExpressionFromList = compact . muJSExpressionList

muJsVarPattern = otherPattern "JSVar" . VariablePattern

muFor inits conds progs body = (ForLoop
(muJSExpressionFromList inits)
(muJSExpressionFromList conds)
Expand All @@ -106,6 +110,7 @@ muFor inits conds progs body = (ForLoop
muForOf kind (JSIdentifier _ id) generator body = (For
[Generator (kind id) (muJSExpression generator)]
(muJSStatement body))
muForIn kind id generator body = other "JSForIn" $ muForOf kind id generator body

muSwitch expression (def, cases) = Switch (muJSExpression expression) (map muCase cases) (headOrElse None . map muDefault $ def)

Expand Down