Assignment03Rules.rsc 1.96 KB
Newer Older
Markus Klinik's avatar
Markus Klinik committed
1
2
3
4
module Assignment03Rules

import Relation;
import IO;
5
import Set;
Markus Klinik's avatar
Markus Klinik committed
6
7
8
9
import lang::java::m3::Core;
import lang::java::m3::AST;
import Message;

10
import ImplementsAbstractMethod;
Markus Klinik's avatar
Markus Klinik committed
11
12
import ClassHierarchy;
import Util;
13

14
15
// Runs all checkers for assignment 3 on the given model
set[Message] allAssignment03Rules(M3 model)
Markus Klinik's avatar
Markus Klinik committed
16
17
18
  = a03_geometric_is_comparable(model)
  + a03_shapes_implement_comparable(model)
  ;
19

Markus Klinik's avatar
Markus Klinik committed
20
21
set[Message] a03_geometric_is_comparable(M3 model)
{
Markus Klinik's avatar
Markus Klinik committed
22
23
  set[Message] result = {};
  try
Markus Klinik's avatar
retab    
Markus Klinik committed
24
  {
Markus Klinik's avatar
Markus Klinik committed
25
26
27
28
29
    geometric = findInterface(model, "Geometric");
    if( ! ("Comparable" in { super.file | super <- model.extends[geometric] }) )
    {
      result += { error("Geometric should extend Comparable", geometric) };
    }
Markus Klinik's avatar
retab    
Markus Klinik committed
30
  }
Markus Klinik's avatar
Markus Klinik committed
31
  catch error:
Markus Klinik's avatar
retab    
Markus Klinik committed
32
  {
Markus Klinik's avatar
Markus Klinik committed
33
    return { error };
Markus Klinik's avatar
retab    
Markus Klinik committed
34
  }
Markus Klinik's avatar
Markus Klinik committed
35

Markus Klinik's avatar
Markus Klinik committed
36
  return result;
37
38
39
40
41
}


set[Message] a03_shapes_implement_comparable(M3 model)
{
Markus Klinik's avatar
Markus Klinik committed
42
43
  set[Message] result = {};
  try
Markus Klinik's avatar
retab    
Markus Klinik committed
44
  {
Markus Klinik's avatar
Markus Klinik committed
45
    geometric = findInterface(model, "Geometric");
Markus Klinik's avatar
Markus Klinik committed
46

Markus Klinik's avatar
Markus Klinik committed
47
48
49
50
51
52
    // There should be exactly two subclasses of Geometric
    shapes = invert(model.implements)[geometric];
    if( {"Rectangle", "Circle"} != { getName(model, shape) | shape <- shapes } )
    {
      return { error("There should be two implementations of Geometric: Rectangle and Circle", geometric) };
    }
53

Markus Klinik's avatar
Markus Klinik committed
54

Markus Klinik's avatar
Markus Klinik committed
55
56
57
58
59
60
61
    // Rectangle and Circle should only implement Geometric and nothing else
    result += union(
      { model.implements[shape] == { geometric }
        ? {}
        : { error("<getName(model,shape)> should implement Geometric and nothing else", shape) }
      | shape <- shapes
      });
Markus Klinik's avatar
Markus Klinik committed
62

Markus Klinik's avatar
Markus Klinik committed
63
64
    // Rectangle and Circle should implement Comparable.compareTo
    loc compareTo = |java+method:///java/lang/Comparable/compareTo(T)|;
Markus Klinik's avatar
Markus Klinik committed
65

Markus Klinik's avatar
Markus Klinik committed
66
67
    // for every shape: one of the methods has to override compareTo
    for( shape <- shapes )
Markus Klinik's avatar
retab    
Markus Klinik committed
68
    {
Markus Klinik's avatar
Markus Klinik committed
69
70
71
72
      if( !implementsAbstractMethod(model,shape,compareTo) )
      {
        result += error("<shape.file> should override Comparable.compareTo", shape);
      }
Markus Klinik's avatar
retab    
Markus Klinik committed
73
74
    }
  }
Markus Klinik's avatar
Markus Klinik committed
75
76
77
78
  catch error:
  {
    return { error };
  }
Markus Klinik's avatar
Markus Klinik committed
79

Markus Klinik's avatar
Markus Klinik committed
80
  return result;
Markus Klinik's avatar
retab    
Markus Klinik committed
81
}