Skip to content

Commit

Permalink
Merge pull request #111 from mumuki/fix-confusing-domain-language-det…
Browse files Browse the repository at this point in the history
…ections

Perform domain smells analysis only on main expressions
  • Loading branch information
flbulgarelli authored Oct 18, 2017
2 parents edbbf9d + ef1a6bb commit b136d4b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 11 deletions.
28 changes: 21 additions & 7 deletions spec/DomainLanguageSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module DomainLanguageSpec (spec) where

import Test.Hspec
import Language.Mulang.Ast
import Language.Mulang.Inspector.Combiner (detect)
import Language.Mulang.DomainLanguage (DomainLanguage(..), hasMisspelledIdentifiers, hasTooShortIdentifiers, hasWrongCaseIdentifiers)
import Language.Mulang.Parsers.Haskell (hs)
import Language.Mulang.Parsers.JavaScript (js)
Expand All @@ -16,6 +17,7 @@ spec = do

describe "hasTooShortIdentifiers" $ do
let run = hasTooShortIdentifiers language
let runDetection = detect (hasTooShortIdentifiers language)

it "is True when it is a one-char identifier" $ do
run (hs "x = True") `shouldBe` True
Expand All @@ -32,23 +34,35 @@ spec = do
it "is False when it contains a short parameter name" $ do
run (hs "aFunction a = a") `shouldBe` False

it "is True when it contains a short local variable name" $ do
run (js "function foo() { var x = 1; return x }") `shouldBe` True
it "is False when it contains a short local variable name, but it is detected" $ do
let sample = js "function foo() { var x = 1; return x }"

run sample `shouldBe` False
runDetection sample `shouldBe` ["x"]

it "is False when it uses a short named function" $ do
run (hs "aFunction aNumber = f aNumber") `shouldBe` False

it "is False when it contains a short local variable name in a method" $ do
run (js "var pepita = {come:function(){var x = 1; }, vola:function(){}};") `shouldBe` True
it "is False when it contains a short local variable name in a method, but it is detected" $ do
let sample = js "var pepita = {come:function(){var x = 1; }, vola:function(){}};"

runDetection sample `shouldBe` ["x"]
run sample `shouldBe` False

it "is False when it contains a short local parameter name in a method" $ do
run (js "var pepita = {come:function(x){ }, vola:function(){}};") `shouldBe` False

it "is True when it contains a short named method" $ do
run (js "var pepita = {x:function(){}, vola:function(){}};") `shouldBe` True
it "is False when it contains a short named method, but it is detected" $ do
let sample = js "var pepita = {x:function(){}, vola:function(){}};"

runDetection sample `shouldBe` ["x"]
run sample `shouldBe` False

it "is True when it contains a short named attribute" $ do
run (js "var pepita = {x: 2, vola:function(){}};") `shouldBe` True
let sample = js "var pepita = {x: 2, vola:function(){}};"

runDetection sample `shouldBe` ["x"]
run sample `shouldBe` False

it "is True when it contains a short variable name" $ do
run (js "var x = 3;") `shouldBe` True
Expand Down
16 changes: 16 additions & 0 deletions spec/SmellsAnalyzerSpec.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module SmellsAnalyzerSpec(spec) where

import Language.Mulang.Analyzer hiding (result, spec)
import Language.Mulang.Ast
import Test.Hspec

result smellResults = AnalysisCompleted [] smellResults []
Expand All @@ -9,6 +10,21 @@ runExcept language content smells = analyse (smellsAnalysis (CodeSample language
runOnly language content smells = analyse (smellsAnalysis (CodeSample language content) noSmells { include = Just smells })

spec = describe "SmellsAnalyzer" $ do
describe "Using domain language and nested structures" $ do
let runRuby sample = analyse (domainLanguageAnalysis (MulangSample sample) (DomainLanguage Nothing (Just RubyCase) (Just 3) Nothing))
it "works with empty set" $ do
(runRuby (Sequence [
(Object "Foo_Bar" (Sequence [
(SimpleMethod "y" [] MuNull),
(SimpleMethod "aB" [] MuNull),
(SimpleMethod "fooBar" [] MuNull)])),
(Object "Foo" MuNull)])) `shouldReturn` (result [
Expectation "y" "HasTooShortIdentifiers",
Expectation "aB" "HasTooShortIdentifiers",
Expectation "Foo_Bar" "HasWrongCaseIdentifiers",
Expectation "aB" "HasWrongCaseIdentifiers",
Expectation "fooBar" "HasWrongCaseIdentifiers"])

describe "Using exclusion" $ do
it "works with empty set" $ do
(runExcept Haskell "fun x = if x then True else False" []) `shouldReturn` (result [Expectation "fun" "HasRedundantIf"])
Expand Down
4 changes: 4 additions & 0 deletions src/Language/Mulang/Analyzer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Language.Mulang.Analyzer (
emptyAnalysisSpec,

emptyAnalysis,
domainLanguageAnalysis,
expectationsAnalysis,
smellsAnalysis,
signaturesAnalysis,
Expand Down Expand Up @@ -37,6 +38,9 @@ emptyAnalysisSpec = AnalysisSpec [] noSmells Nothing Nothing
emptyAnalysis :: Sample -> Analysis
emptyAnalysis code = Analysis code emptyAnalysisSpec

domainLanguageAnalysis :: Sample -> DomainLanguage -> Analysis
domainLanguageAnalysis code domainLanguage = Analysis code (emptyAnalysisSpec { domainLanguage = Just domainLanguage, smellsSet = allSmells })

expectationsAnalysis :: Sample -> [Expectation] -> Analysis
expectationsAnalysis code es = Analysis code (emptyAnalysisSpec { expectations = es })

Expand Down
8 changes: 4 additions & 4 deletions src/Language/Mulang/DomainLanguage.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Language.Mulang.DomainLanguage (

import Language.Mulang.Inspector (Inspection)
import Language.Mulang.Ast (Expression)
import Language.Mulang.Generator (declaredIdentifiers)
import Language.Mulang.Generator (mainDeclaredIdentifiers)

import Text.Dictionary (Dictionary, exists)

Expand All @@ -22,7 +22,7 @@ data DomainLanguage = DomainLanguage {
type DomainLanguageInspection = DomainLanguage -> Inspection

hasTooShortIdentifiers :: DomainLanguageInspection
hasTooShortIdentifiers language = any isShort . declaredIdentifiers
hasTooShortIdentifiers language = any isShort . mainDeclaredIdentifiers
where isShort identifier = length identifier < (minimumIdentifierSize language) && notJargonOf identifier language

hasMisspelledIdentifiers :: DomainLanguageInspection
Expand All @@ -32,10 +32,10 @@ hasMisspelledIdentifiers language = any isMisspelled . wordsOf language

hasWrongCaseIdentifiers :: DomainLanguageInspection
hasWrongCaseIdentifiers (DomainLanguage _ style _ _)
= any (not . canTokenize style) . declaredIdentifiers
= any (not . canTokenize style) . mainDeclaredIdentifiers

wordsOf :: DomainLanguage -> Expression -> [String]
wordsOf (DomainLanguage _ style _ _) = concatMap (tokenize style) . declaredIdentifiers
wordsOf (DomainLanguage _ style _ _) = concatMap (tokenize style) . mainDeclaredIdentifiers

emptyDictionary = null . dictionary

Expand Down
5 changes: 5 additions & 0 deletions src/Language/Mulang/Generator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Language.Mulang.Generator (
declarations,
declarationsOf,
declaredIdentifiers,
mainDeclaredIdentifiers,
equationBodies,
expressions,
referencedIdentifiers,
Expand Down Expand Up @@ -100,6 +101,10 @@ transitiveReferencedIdentifiers identifier code = expand (concatMap referencedI
declaredIdentifiers :: Generator Identifier
declaredIdentifiers = map fst . declarations

mainDeclaredIdentifiers :: Generator Identifier
mainDeclaredIdentifiers (Sequence _) = []
mainDeclaredIdentifiers expression = take 1 . declaredIdentifiers $ expression

-- | Returns all the body equations of functions, procedures and methods
equationBodies :: Generator EquationBody
equationBodies = concatMap (bodiesOf . snd) . declarations
Expand Down

0 comments on commit b136d4b

Please sign in to comment.