Example #1
0
func TestSelector_deep_nesting(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `a {
	c, d, e {
	  f, g, h {
      m, n, o {
        color: blue;
      }
    }
	}
}`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `a c f m, a c f n, a c f o, a c g m, a c g n, a c g o, a c h m, a c h n, a c h o, a d f m, a d f n, a d f o, a d g m, a d g n, a d g o, a d h m, a d h n, a d h o, a e f m, a e f n, a e f o, a e g m, a e g n, a e g o, a e h m, a e h n, a e h o {
  color: blue; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #2
0
func TestDirective_each_paran(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `div {
  @each $i in (1 2 3 4 5) {
   i: $i;
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  i: 1;
  i: 2;
  i: 3;
  i: 4;
  i: 5; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #3
0
func TestDecl_if(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()

	input := `$x: 1 2;
@if type-of(nth($x, 2)) == number {
  div {
    background: gray;
  }
}
@else if type-of(nth($x, 2)) == string {
  div {
    background: blue;
  }
}
@else {
  div {
    background: green;
  }
}
`
	ctx.SetMode(parser.Trace)
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  background: gray; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #4
0
func TestDecl_func_if(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `$x: true;

@function foobar() {
  @if $x {
    $x: false !global;
    @return foo;
  }
}

div {
  content: foobar();
}
`
	ctx.SetMode(parser.Trace)
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  content: foo; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #5
0
func TestSelector_selector_interp(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `$x: oo, ba;
$y: az, hu;

f#{$x}r {
  p: 1;
  b#{$y}x {
    q: 2;
    mumble#{length($x) + length($y)} {
      r: 3;
    }
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `foo, bar {
  p: 1; }
  foo baz, foo hux, bar baz, bar hux {
    q: 2; }
    foo baz mumble4, foo hux mumble4, bar baz mumble4, bar hux mumble4 {
      r: 3; }
`

	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}

}
Example #6
0
func testString(t *testing.T, in string, mode Mode) (*ast.File, *token.FileSet) {
	fset := token.NewFileSet()
	f, err := ParseFile(fset, "testfile", in, mode)
	if err != nil {
		t.Fatal(err)
	}
	return f, fset

}
Example #7
0
func TestUnitMath(t *testing.T) {
	const src = `
$a: 3px + 3px;
div {
  width: $a;
}
`
	f, err := ParseFile(token.NewFileSet(), "", src, 0)
	if err != nil {
		t.Fatal(err)
	}

	objects := map[string]ast.ObjKind{
		"$color": ast.Var,
		"$list":  ast.Var,
	}
	ast.Inspect(f, func(n ast.Node) bool {
		if spec, ok := n.(*ast.RuleSpec); ok {
			ast.Print(token.NewFileSet(), spec)
		}
		return true
		if ident, ok := n.(*ast.Ident); ok {
			return true
			obj := ident.Obj
			if obj == nil {
				if objects[ident.Name] != ast.Bad {
					t.Errorf("no object for %s", ident.Name)
				}
				return true
			}
			if obj.Name != ident.Name {
				t.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj.Name, ident.Name)
			}
			kind := objects[ident.Name]
			if obj.Kind != kind {
				t.Errorf("%s: obj.Kind = %s; want %s", ident.Name, obj.Kind, kind)
			}
		}
		return true
	})
}
Example #8
0
func TestImports(t *testing.T) {
	for path, isValid := range imports {
		src := fmt.Sprintf("@import %s;", path)
		_, err := ParseFile(token.NewFileSet(), "", src, 0) // Trace
		switch {
		case err != nil && isValid:
			t.Errorf("ParseFile(%s): got %v; expected no error", src, err)
		case err == nil && !isValid:
			t.Errorf("ParseFile(%s): got no error; expected one", src)
		}
	}
}
Example #9
0
func runParse(t *testing.T, in string, e string) {
	ctx := NewContext()
	// ctx.SetMode(parser.Trace)
	ctx.fset = token.NewFileSet()

	bout, err := ctx.run("", in)
	if err != nil {
		t.Fatal(err)
	}
	out := string(bout)
	if e != out {
		t.Errorf("got:\n%q\nwanted:\n%q", out, e)
	}
}
Example #10
0
func (ctx *Context) run(path string, src interface{}) ([]byte, error) {

	ctx.fset = token.NewFileSet()
	// ctx.mode = parser.Trace
	pf, err := parser.ParseFile(ctx.fset, path, src, ctx.mode)
	if err != nil {
		return nil, err
	}

	ast.Walk(ctx, pf)
	lr, _ := utf8.DecodeLastRune(ctx.buf.Bytes())
	_ = lr
	if ctx.buf.Len() > 0 && lr != '\n' {
		ctx.out("\n")
	}
	// ctx.printSels(pf.Decls)
	return ctx.buf.Bytes(), nil
}
Example #11
0
func TestSelector_combinators(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `a + b ~ c { color: red; }
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `a + b ~ c {
  color: red; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}

}
Example #12
0
func TestBinary_math(t *testing.T) {
	const src = `
$a: inspect(1 + 3);
$b: inspect(3/1);
$c: inspect(1/2 + 1/2);
$d: inspect(2*2);
$d: inspect(1*1/2);
$e: inspect(1/2*1/2);
$f: inspect(2*2/2*2);

//$o: inspect(3px + 3px + 3px);
`
	f, err := ParseFile(token.NewFileSet(), "", src, 0|Trace)
	if err != nil {
		t.Fatal(err)
	}

	lits := []string{
		"4",
		"3",
		"1",
		"4",
		"0.5",
		"0.25",
		"4",
	}
	var pos int
	ast.Inspect(f, func(n ast.Node) bool {
		if call, ok := n.(*ast.CallExpr); ok {
			// ident := call.Fun.(*ast.Ident)
			lit := call.Resolved.(*ast.BasicLit)
			val := lits[pos]
			pos++

			if val != lit.Value {
				t.Errorf("useful ident here got: %s wanted %s", lit.Value, val)
			}
		}
		return true
	})

}
Example #13
0
func TestSelector_many_nests(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `a, b {
c, d { color: red; }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `a c, a d, b c, b d {
  color: red; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #14
0
func TestInterp(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `div {
  hello: #{123+321};
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  hello: 444; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #15
0
func register(s string, ch builtin.CallFunc, h builtin.CallHandle) {
	fset := token.NewFileSet()
	pf, err := ParseFile(fset, "", s, FuncOnly)
	if err != nil {
		if !strings.HasSuffix(err.Error(), "expected ';', found 'EOF'") {
			log.Fatal(err)
		}
	}
	d := &desc{c: call{
		ch:     ch,
		handle: h,
	}}
	ast.Walk(d, pf.Decls[0])
	if d.err != nil {
		log.Fatal("failed to parse func description", d.err)
	}
	if _, ok := builtins[d.c.name]; ok {
		log.Println("already registered", d.c.name)
	}
	builtins[d.c.name] = d.c
}
Example #16
0
func TestSelector_comboampersand(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `div ~ b {
& + & { color: red; }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal("compilation fail", err)
	}

	e := `div ~ b + div ~ b {
  color: red; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}

}
Example #17
0
func TestSelector_singleampersand(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `div {
& { color: red; }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  color: red; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}

}
Example #18
0
func TestSelector_nesting_child_group(t *testing.T) {

	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `a {
b, c { color: red; }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `a b, a c {
  color: red; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #19
0
func TestSpec_files(t *testing.T) {

	inputs, err := filepath.Glob("../sass-spec/spec/basic/*/input.scss")
	if err != nil {
		t.Fatal(err)
	}

	mode := DeclarationErrors
	mode = Trace | ParseComments
	var name string
	for _, name = range inputs {
		if strings.Contains(name, "25_") && testing.Short() {
			// This is the last test we currently parse properly
			return
		}
		if !strings.Contains(name, "29_") {
			continue
		}
		if strings.Contains(name, "06_") {
			continue
		}
		if strings.Contains(name, "14_") {
			continue
		}
		// These are f****d things in Sass like lists
		if strings.Contains(name, "15_") {
			continue
		}
		// namespaces are wtf
		if strings.Contains(name, "24_") {
			continue
		}
		fmt.Println("Parsing", name)
		_, err := ParseFile(token.NewFileSet(), name, nil, mode)
		if err != nil {
			t.Fatalf("ParseFile(%s): %v", name, err)
		}
		fmt.Println("Parsed", name)
	}
}
Example #20
0
func TestSelector_inplace_nesting(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `hey, ho {
  foo &.goo {
    color: blue;
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `foo hey.goo, foo ho.goo {
  color: blue; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #21
0
func TestSelector_nesting_implicit_unary(t *testing.T) {

	ctx := NewContext()
	ctx.fset = token.NewFileSet()
	input := `a {
  > e {
    color: blue;
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `a > e {
  color: blue; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #22
0
func TestInterp_copy(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `div {
  @each $i in 1 2 {
    hello: text#{$i};
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  hello: text1;
  hello: text2; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #23
0
func TestDirective_each(t *testing.T) {
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `div {
  @each $i in a b c {
   i: $i;
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `div {
  i: a;
  i: b;
  i: c; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #24
0
func TestSelector_nesting_unary(t *testing.T) {

	// This is bizarre, may never support this odd syntax
	ctx := NewContext()

	ctx.fset = token.NewFileSet()
	input := `a {
  & > e {
    color: blue;
  }
}
`
	out, err := ctx.runString("", input)
	if err != nil {
		t.Fatal(err)
	}

	e := `a > e {
  color: blue; }
`
	if e != out {
		t.Fatalf("got:\n%s\nwanted:\n%s", out, e)
	}
}
Example #25
0
func checkErrors(t *testing.T, filename string, input interface{}) {
	src, err := readSource(filename, input)
	if err != nil {
		t.Error(err)
		return
	}

	fset := token.NewFileSet()
	mode := DeclarationErrors | AllErrors
	_, err = ParseFile(fset, filename, src, mode)
	found, ok := err.(scanner.ErrorList)
	if err != nil && !ok {
		t.Error(err)
		return
	}
	found.RemoveMultiples()

	// we are expecting the following errors
	// (collect these after parsing a file so that it is found in the file set)
	expected := expectedErrors(t, fset, filename, src)

	// verify errors returned by the parser
	compareErrors(t, fset, expected, found)
}
Example #26
0
func TestObjects(t *testing.T) {
	const src = `
$color: red;
$list: 1 2 $color;
`
	f, err := ParseFile(token.NewFileSet(), "", src, 0)
	if err != nil {
		t.Fatal(err)
	}

	objects := map[string]ast.ObjKind{
		"$color": ast.Var,
		"$list":  ast.Var,
	}

	ast.Inspect(f, func(n ast.Node) bool {
		if ident, ok := n.(*ast.Ident); ok {

			obj := ident.Obj
			if obj == nil {
				if objects[ident.Name] != ast.Bad {
					t.Errorf("no object for %s", ident.Name)
				}
				return true
			}
			if obj.Name != ident.Name {
				t.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj.Name, ident.Name)
			}
			kind := objects[ident.Name]
			if obj.Kind != kind {
				t.Errorf("%s: obj.Kind = %s; want %s", ident.Name, obj.Kind, kind)
			}
		}
		return true
	})
}
Example #27
0
	{token.MIXIN, "@mixin"},*/
	// {token.SELECTOR, "foo($a,$b)"},
	// {token.COLOR, "rgb(10,10,10)"},
}

var source = func(tokens []elt) []byte {
	var src []byte
	for _, t := range tokens {
		src = append(src, t.lit...)
		src = append(src, whitespace...)
	}

	return src
}

var fset = token.NewFileSet()

func newlineCount(s string) int {
	n := 0
	for i := 0; i < len(s); i++ {
		if s[i] == '\n' {
			n++
		}
	}
	return n
}

func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
	pos := fset.Position(p)
	if pos.Filename != expected.Filename {
		t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename)
Example #28
0
// ParseExpr is a convenience function for obtaining the AST of an expression x.
// The position information recorded in the AST is undefined. The filename used
// in error messages is the empty string.
//
func ParseExpr(x string) (ast.Expr, error) {
	return ParseExprFrom(token.NewFileSet(), "", []byte(x), 0)
}
Example #29
0
func printEach(ctx *Context, n ast.Node) {
	// surprise, not media but behavior is same!
	ctx.hiddenBlock = true
	fmt.Println("each...")
	ast.Print(token.NewFileSet(), n)
}