use ASM to parse the class file

use ASM to parse the class file

namespace Boojay.Compilation.TypeSystem

import System
import System.Collections.Generic
import System.IO

import java.util.jar

import Boo.Lang.Useful.Attributes

import Boo.Lang.Compiler
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Core
import Boo.Lang.Compiler.TypeSystem.Services

import org.objectweb.asm
import org.objectweb.asm.commons

class JarTypeSystemProvider:

	def ForJar(jar as string):
		return JarCompileUnit(jar)

class JarCompileUnit(ICompileUnit):

	_root as JarRootNamespace

	def constructor(jar as string):
		_root = JarRootNamespace(jar)

	EntityType:
		get: return EntityType.CompileUnit

	Name:
		get: return _root.Jar.getName()

	FullName:
		get: return Name

	RootNamespace:
		get: return _root

class JarRootNamespace(AbstractNamespace):

	[getter(Jar)]
	_jar as JarFile

	def constructor(jar as string):
		_jar = JarFile(jar)

	[once]
	override def GetMembers():
		return array(LoadMembers())

	private def LoadMembers() as IEntity*:
		entries = _jar.entries()
		while entries.hasMoreElements():
			entry as JarEntry = entries.nextElement()
			entryName = entry.getName()
			continue unless entryName.EndsWith(".class")
			assert not entry.isDirectory()

			yield JarClass(_jar, entry)

class JarClass(AbstractType):

	_jar as JarFile
	_entry as JarEntry
	_name as string

	def constructor(jar as JarFile, entry as JarEntry):
		_jar = jar
		_entry = entry
		_name = Path.GetFileNameWithoutExtension(entry.getName())

	override Name:
		get: return _name

	override EntityType:
		get: return EntityType.Type

	[once]
	override def GetMembers():
		return array(LoadMembers())

	def Resolve(result as ICollection[of IEntity], name as string, typesToConsider as EntityType):
		return my(NameResolutionService).Resolve(name, GetMembers(), typesToConsider, result)

	private def LoadMembers() as IEntity*:
		reader = ClassReader(_jar.getInputStream(_entry))
		visitor = ClassFileParser(self)
		flags = ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES
		reader.accept(visitor, flags)
		return visitor.Members

class ClassFileParser(EmptyVisitor):

	_declaringType as IType
	[getter(Members)] _members = List[of IEntity]()

	def constructor(declaringType as IType):
		_declaringType = declaringType

	override def visit(version as int, access as int, name as string,
			signature as string, superName as string,
			interfaces as (string)):
		pass

	override def visitMethod(access as int, name as string,
					desc as string, signature as string, exceptions as (string)):
		method = JavaMethod(_declaringType, name)
		_members.Add(method)
		return super(access, name, desc, signature, exceptions)

class JavaMethod(IMethod):

	_declaringType as IType
	_name as string

	def constructor(declaringType as IType, name as string):
		_declaringType = declaringType
		_name = name

	EntityType:
		get: return EntityType.Method

	Name:
		get: return _name

	FullName:
		get: return "${_declaringType.FullName}.${_name}"

	DeclaringType:
		get: return _declaringType

	def GetParameters():
		return array[of IParameter](0)

namespace Boojay.Compilation.TypeSystem

import System
import System.Collections.Generic
import System.IO

import java.util.jar

import Boo.Lang.Useful.Attributes

import Boo.Lang.Compiler
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Core
import Boo.Lang.Compiler.TypeSystem.Services

class JarTypeSystemProvider:

	def ForJar(jar as string):
		return JarCompileUnit(jar)

class JarCompileUnit(ICompileUnit):

	_root as JarRootNamespace

	def constructor(jar as string):
		_root = JarRootNamespace(jar)

	EntityType:
		get: return EntityType.CompileUnit

	Name:
		get: return _root.Jar.getName()

	FullName:
		get: return Name

	RootNamespace:
		get: return _root

class JarRootNamespace(AbstractNamespace):

	[getter(Jar)]
	_jar as JarFile

	def constructor(jar as string):
		_jar = JarFile(jar)

	[once]
	override def GetMembers():
		return array(LoadMembers())

	private def LoadMembers() as IEntity*:
		entries = _jar.entries()
		while entries.hasMoreElements():
			entry as JarEntry = entries.nextElement()
			entryName = entry.getName()
			continue unless entryName.EndsWith(".class")
			assert not entry.isDirectory()

			yield JarClass(_jar, entry)

class JarClass(AbstractType):

	_jar as JarFile
	_entry as JarEntry
	_name as string

	def constructor(jar as JarFile, entry as JarEntry):
		_jar = jar
		_entry = entry
		_name = Path.GetFileNameWithoutExtension(entry.getName())

	override Name:
		get: return _name

	override EntityType:
		get: return EntityType.Type

	[once]
	override def GetMembers():
		return array(LoadMembers())

	def Resolve(result as ICollection[of IEntity], name as string, typesToConsider as EntityType):
		return my(NameResolutionService).Resolve(name, GetMembers(), typesToConsider, result)

	private def LoadMembers() as IEntity*:
		yield JavaMethod(self)

class JavaMethod(IMethod):

	_declaringType as IType

	def constructor(declaringType as IType):
		_declaringType = declaringType

	EntityType:
		get: return EntityType.Method

	Name:
		get: return "getName"

	FullName:
		get: return "Foo.getName"

	DeclaringType:
		get: return _declaringType

	def GetParameters():
		return array[of IParameter](0)


RuntimeServices.ToBool

RuntimeServices.ToBool

namespace Boojay.Runtime

import java.lang
import java.util

static class RuntimeServices:

	def ToBool(o):
		if o is null: return false
		boolean = o as Boolean
		if boolean is not null: return boolean.booleanValue()
		return true

	def UnboxChar(o):
		return cast(Character, o).charValue()

	def BoxChar(ch as char):
		return Character(ch)

	def EqualityOperator(x, y):
		if x is y: return true
		if x is null: return false
		return x.Equals(y)

	def GetEnumerable(source) as Enumerable:
		if source isa Iterable:
			return IterableEnumerable(source)
		if source isa string:
			return StringEnumerable(source)
		raise IllegalArgumentException("source")

internal class StringEnumerable(Enumerable):
	_string as string
	def constructor(value as string):
		_string = value
	def GetEnumerator():
		return StringEnumerator(_string)

internal class StringEnumerator(Enumerator):

	_string as string
	_current = -1

	def constructor(value as string):
		_string = value

	def MoveNext():
		next = _current + 1
		if next >= len(_string):
			return false
		_current = next
		return true

	Current:
		get: return _string[_current]

internal class IterableEnumerable(Enumerable):
	_iterable as Iterable
	def constructor(iterable as Iterable):
		_iterable = iterable
	def GetEnumerator() as Enumerator:
		return IteratorEnumerator(_iterable.iterator())

internal class IteratorEnumerator(Enumerator):

	_iterator as Iterator
	_current

	def constructor(iterator as Iterator):
		_iterator = iterator

	def MoveNext():
		if not _iterator.hasNext(): return false
		_current = _iterator.next()
		return true

	Current:
		get: return _current

namespace Boojay.Runtime

import java.lang
import java.util

static class RuntimeServices:

	def UnboxChar(o):
		return cast(Character, o).charValue()

	def BoxChar(ch as char):
		return Character(ch)

	def EqualityOperator(x, y):
		if x is y: return true
		if x is null: return false
		return x.Equals(y)

	def GetEnumerable(source) as Enumerable:
		if source isa Iterable:
			return IterableEnumerable(source)
		if source isa string:
			return StringEnumerable(source)
		raise IllegalArgumentException("source")

internal class StringEnumerable(Enumerable):
	_string as string
	def constructor(value as string):
		_string = value
	def GetEnumerator():
		return StringEnumerator(_string)

internal class StringEnumerator(Enumerator):

	_string as string
	_current = -1

	def constructor(value as string):
		_string = value

	def MoveNext():
		next = _current + 1
		if next >= len(_string):
			return false
		_current = next
		return true

	Current:
		get: return _string[_current]

internal class IterableEnumerable(Enumerable):
	_iterable as Iterable
	def constructor(iterable as Iterable):
		_iterable = iterable
	def GetEnumerator() as Enumerator:
		return IteratorEnumerator(_iterable.iterator())

internal class IteratorEnumerator(Enumerator):

	_iterator as Iterator
	_current

	def constructor(iterator as Iterator):
		_iterator = iterator

	def MoveNext():
		if not _iterator.hasNext(): return false
		_current = _iterator.next()
		return true

	Current:
		get: return _current


Update build script

Update build script

solution_file = "GitAspx.sln"
project_file = "GitAspx/GitAspx.csproj"

target default, (init, compile, test, deploy, package):
  pass

target init:
  rm("build")

target compile:
  msbuild(file: solution_file, configuration: "release", version: "4")

target test:
  pass # Need to implement

target deploy:
  msbuild(file: project_file, configuration: "release", version: "4", targets: ("_CopyWebApplication",), properties: { "OutDir": "../build/" }, verbosity: "normal")

target package:
  zip("Build/_PublishedWebsites/Gitaspx", "Build/GitAspx.zip")

solution_file = "GitAspx.sln"
project_file = "GitAspx/GitAspx.csproj"

target default, (init, compile, test, deploy, package):
  pass

target init:
  rm("build")

target compile:
  msbuild(file: solution_file, configuration: "release", version: "4")

target test:
  pass # Need to implement

target deploy:
  msbuild(file: project_file, configuration: "release", version: "4", targets: ("_CopyWebApplication",), properties: { "OutDir": "../build/" }, verbosity: "normal")

target package:
  pass


preparing

preparing

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@1564 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.Lang.Tests

import NUnit.Framework
import Boo.IO
import System.IO
import System.Text

[TestFixture]
class TextFileFixture:

	[Test]
	def TestReadFile():

		fname = WriteTempFile("cabeÃ§Ã£o", Encoding.Default)
		Assert.AreEqual("cabeÃ§Ã£o", TextFile.ReadFile(fname))

		fname = WriteTempFile("cabeÃ§Ã£o", Encoding.UTF8)
		Assert.AreEqual("cabeÃ§Ã£o", TextFile.ReadFile(fname))

	[Test]
	def TestWriteFile():
		TextFile.WriteFile(fname=Path.GetTempFileName(), "zuÃ§aqÃ¼istÃ£o")
		Assert.AreEqual("zuÃ§aqÃ¼istÃ£o", ReadUTF8File(fname))

	def ReadUTF8File(fname as string):
		using reader=File.OpenText(fname):
			return reader.ReadToEnd()

	def WriteTempFile(content as string, encoding as Encoding) as string:
		using writer=StreamWriter(File.OpenWrite(fname=Path.GetTempFileName()), encoding):
			writer.Write(content)
			return fname


code completion patch by Arron Washington

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@1296 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

"""
Interactive Forms-based Console
"""

namespace booish.gui

import System
import System.Text
import System.IO
import System.Reflection
import booish
import System.Windows.Forms
import System.Drawing
import System.Runtime.InteropServices

class KeyChar:

	public static Enter = chr(Keys.Enter)

	public static Dot = chr('.')

	public static Back = chr(Keys.Back)

	public static Esc = chr(Keys.Escape)

class CompletionBox(ListBox):

	_interpreter as InteractiveInterpreter

	def constructor(interpreter):
		self._interpreter = interpreter
		self.Visible = false

	def Fill(type as System.Type):

		members = []
		for member in type.GetMembers():
			if IsValidSuggestion(member):
				if member isa FieldInfo:
					field = member as FieldInfo
					members.Add("${field.Name} as ${getBooTypeName(field.FieldType)}")
				elif member isa PropertyInfo:
					property = member as PropertyInfo
					getField = ("", "getter,")[property.CanRead]
					setField = ("", "setter")[property.CanWrite]
					members.Add("${member.Name} as ${getBooTypeName(property.PropertyType)} (${getField} ${setField})")
				elif member isa MethodInfo:
					method = member as MethodInfo
					params = join("${param.Name} as ${getBooTypeName(param.ParameterType)}"
										for param in method.GetParameters())
					returnValue = ""
					returnValue = " as ${getBooTypeName(method.ReturnType)}" if method.ReturnType is not void
					members.Add("${member.Name}(${params})${returnValue}")

		Items.Clear()
		for item in members.Sort():
			Items.Add(item)

	def Show(pos as Point):
		self.Location = pos
		self.Visible = true
		self.Focus()

	private def IsValidSuggestion(member as MemberInfo):
		return false if not IsPublic(member)
		method = member as MethodBase
		if method is not null:
			return false if method.IsSpecialName
		return true

	private def IsPublic(member as MemberInfo):
		if MemberTypes.Method == member.MemberType:
			return cast(MethodBase, member).IsPublic
		if MemberTypes.Property == member.MemberType:
			p as PropertyInfo = member
			return (p.GetGetMethod() or p.GetSetMethod()).IsPublic
		if MemberTypes.Field == member.MemberType:
			return cast(FieldInfo, member).IsPublic
		return true

	override def OnLostFocus(args as EventArgs):
		self.Visible = false
		super(args)

	override def OnKeyPress(args as KeyPressEventArgs):
		finish = def ():
			Parent.Focus()
			args.Handled = true

		if args.KeyChar in KeyChar.Esc, KeyChar.Back:
			finish()
		elif KeyChar.Enter == args.KeyChar:
			cast(TextBox, Parent).SelectedText = /\w+/.Match(SelectedItem).Groups[0].Value
			finish()
		else:
			super(args)

	private def getBooTypeName(type as System.Type):
		return _interpreter.getBooTypeName(type)

class PromptBox(TextBox):

	enum InputState:
		SingleLine = 0
		Block = 1

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

	_console = StringWriter()

	[getter(Interpreter)]
	_interpreter = InteractiveInterpreter(
								RememberLastValue: true,
								Print: print)

	_completionBox = CompletionBox(_interpreter)

	def constructor():
		self.Dock = DockStyle.Fill
		self.Multiline = true
		self.AcceptsTab = true
		self.ScrollBars = ScrollBars.Vertical
		_interpreter.References.Add(typeof(TextBox).Assembly)
		_interpreter.References.Add(typeof(Font).Assembly)
		_interpreter.SetValue("inspect", inspect)

		Controls.Add(_completionBox)

		prompt()

	CaretPos:
		get:
			p as Point
			assert booish.gui.externs.User32.GetCaretPos(p)
			return p

	def GetCurrentLine():
		line = Lines[-1][4:]
		print("")
		return line

	def SingleLineInputState():
		code = GetCurrentLine()

		if code[-1:] in ":", "\\":
			_state = InputState.Block
			_block.GetStringBuilder().Length = 0
			_block.WriteLine(code)
		else:
			Eval(code)

	def BlockInputState():
		code = GetCurrentLine()
		if 0 == len(code):
			Eval(_block.ToString())
			_state = InputState.SingleLine
		else:
			_block.WriteLine(code)

	override def OnKeyPress(args as KeyPressEventArgs):
		if KeyChar.Enter == args.KeyChar:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			args.Handled = true
		elif KeyChar.Dot == args.KeyChar:
			self.SelectedText = "."
			DotComplete()
			args.Handled = true

		super(args)

	override def OnResize(args as EventArgs):
		_completionBox.Size = System.Drawing.Size(Width*.65, Height*.4)
		super(args)

	def DotComplete():
		m = /((\w|\.)+)\.$/.Match(self.Lines[-1])
		if m.Success:
			// only simple identifiers right now
			expression = m.Groups[1].Value
			if /^\w+$/.IsMatch(expression):
				type = _interpreter.Lookup(expression)
				if type is not null:
					_completionBox.Fill(type)
					_completionBox.Show(CaretPos)

	def Eval(code as string):
		saved = Console.Out
		Console.SetOut(_console)
		try:
			_interpreter.LoopEval(code)
		ensure:
			FlushConsole()
			Console.SetOut(saved)

	def FlushConsole():
		AppendText(_console.ToString())
		_console.GetStringBuilder().Length = 0

	def print(msg):
		AppendText("${msg}\r\n")

	def inspect([required] obj):
		f = Form(Text: "Object Inspector [${obj}]")
		f.Controls.Add(PropertyGrid(
							Dock: DockStyle.Fill,
							SelectedObject: obj,
							Font: Font))
		f.Show()
		return f

	def prompt():
		AppendText((">>> ", "... ")[_state])

def chr(key as Keys):
	return cast(IConvertible, cast(int, key)).ToChar(null)

def chr(s as string):
	assert len(s) == 1
	return s[0]

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

"""
Interactive Forms-based Console
"""

namespace booish.gui

import System
import System.IO
import System.Reflection
import booish
import System.Windows.Forms
import System.Drawing
import System.Runtime.InteropServices

class KeyChar:

	public static Enter = chr(Keys.Enter)

	public static Dot = chr('.')

	public static Back = chr(Keys.Back)

	public static Esc = chr(Keys.Escape)

class CompletionBox(ListBox):

	def constructor():
		self.Visible = false

	def Fill(type as System.Type):

		members = {}
		for member in type.GetMembers():
			if member.Name not in members:
				if IsValidSuggestion(member):
					members.Add(member.Name, member)

		Items.Clear()
		for item in List(members.Keys).Sort():
			Items.Add(item)

	def Show(pos as Point):
		self.Location = pos
		self.Visible = true
		self.Focus()

	private def IsValidSuggestion(member as MemberInfo):
		return false if not IsPublic(member)
		method = member as MethodBase
		if method is not null:
			return false if method.IsSpecialName
		return true

	private def IsPublic(member as MemberInfo):
		if MemberTypes.Method == member.MemberType:
			return cast(MethodBase, member).IsPublic
		if MemberTypes.Property == member.MemberType:
			p as PropertyInfo = member
			return (p.GetGetMethod() or p.GetSetMethod()).IsPublic
		if MemberTypes.Field == member.MemberType:
			return cast(FieldInfo, member).IsPublic
		return true

	override def OnLostFocus(args as EventArgs):
		self.Visible = false
		super(args)

	override def OnKeyPress(args as KeyPressEventArgs):
		finish = def ():
			Parent.Focus()
			args.Handled = true

		if args.KeyChar in KeyChar.Esc, KeyChar.Back:
			finish()
		elif KeyChar.Enter == args.KeyChar:
			cast(TextBox, Parent).SelectedText = SelectedItem
			finish()
		else:
			super(args)

class PromptBox(TextBox):

	enum InputState:
		SingleLine = 0
		Block = 1

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

	_console = StringWriter()

	[getter(Interpreter)]
	_interpreter = InteractiveInterpreter(
								RememberLastValue: true,
								Print: print)

	_completionBox = CompletionBox()

	def constructor():
		self.Dock = DockStyle.Fill
		self.Multiline = true
		self.AcceptsTab = true
		self.ScrollBars = ScrollBars.Vertical
		_interpreter.References.Add(typeof(TextBox).Assembly)
		_interpreter.References.Add(typeof(Font).Assembly)
		_interpreter.SetValue("inspect", inspect)

		Controls.Add(_completionBox)

		prompt()

	CaretPos:
		get:
			p as Point
			assert booish.gui.externs.User32.GetCaretPos(p)
			return p

	def GetCurrentLine():
		line = Lines[-1][4:]
		print("")
		return line

	def SingleLineInputState():
		code = GetCurrentLine()

		if code[-1:] in ":", "\\":
			_state = InputState.Block
			_block.GetStringBuilder().Length = 0
			_block.WriteLine(code)
		else:
			Eval(code)

	def BlockInputState():
		code = GetCurrentLine()
		if 0 == len(code):
			Eval(_block.ToString())
			_state = InputState.SingleLine
		else:
			_block.WriteLine(code)

	override def OnKeyPress(args as KeyPressEventArgs):
		if KeyChar.Enter == args.KeyChar:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			args.Handled = true
		elif KeyChar.Dot == args.KeyChar:
			self.SelectedText = "."
			DotComplete()
			args.Handled = true

		super(args)

	override def OnResize(args as EventArgs):
		_completionBox.Size = System.Drawing.Size(Width*.5, Height*.4)
		super(args)

	def DotComplete():
		m = /((\w|\.)+)\.$/.Match(self.Lines[-1])
		if m.Success:
			// only simple identifiers right now
			expression = m.Groups[1].Value
			if /^\w+$/.IsMatch(expression):
				type = _interpreter.Lookup(expression)
				if type is not null:
					_completionBox.Fill(type)
					_completionBox.Show(CaretPos)

	def Eval(code as string):
		saved = Console.Out
		Console.SetOut(_console)
		try:
			_interpreter.LoopEval(code)
		ensure:
			FlushConsole()
			Console.SetOut(saved)

	def FlushConsole():
		AppendText(_console.ToString())
		_console.GetStringBuilder().Length = 0

	def print(msg):
		AppendText("${msg}\r\n")

	def inspect([required] obj):
		f = Form(Text: "Object Inspector [${obj}]")
		f.Controls.Add(PropertyGrid(
							Dock: DockStyle.Fill,
							SelectedObject: obj,
							Font: Font))
		f.Show()
		return f

	def prompt():
		AppendText((">>> ", "... ")[_state])

def chr(key as Keys):
	return cast(IConvertible, cast(int, key)).ToChar(null)

def chr(s as string):
	assert len(s) == 1
	return s[0]


don't crash when opening a file without an enclosing unityscript project

namespace UnityScript.MonoDevelop.Completion

import System.Collections.Generic

import UnityScript
import UnityScript.MonoDevelop
import UnityScript.MonoDevelop.ProjectModel

import MonoDevelop.Core
import MonoDevelop.Projects
import MonoDevelop.Projects.Dom.Parser
import MonoDevelop.Ide.Gui
import MonoDevelop.Ide.Gui.Content
import MonoDevelop.Ide.CodeCompletion

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.PatternMatching

class UnityScriptEditorCompletion(CompletionTextEditorExtension):

	_dom as ProjectDom
	_resolver as UnityScriptTypeResolver
	_project as DotNetProject

	override def Initialize():
		super()
		_dom = ProjectDomService.GetProjectDom(Document.Project) or ProjectDomService.GetFileDom(Document.FileName)
		InstallUnityScriptSyntaxModeIfNeeded()
		_resolver = UnityScriptTypeResolver()
		_project = Document.Project as DotNetProject
		InitializeProjectReferences()

	def InitializeProjectReferences():
		if _project is null:
			return

		for reference in _project.References:
			if ReferenceType.Project != reference.ReferenceType:
				_resolver.AddReference(reference.Reference)

	def InstallUnityScriptSyntaxModeIfNeeded():
		view = Document.GetContent[of MonoDevelop.SourceEditor.SourceEditorView]()
		return if view is null

		mimeType = UnityScriptParser.MimeType
		return if view.Document.SyntaxMode.MimeType == mimeType

		mode = Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode(mimeType)
		if mode is not null:
			view.Document.SyntaxMode = mode
		else:
			LoggingService.LogWarning(GetType() + " could not get SyntaxMode for mimetype '" + mimeType + "'.")

	override def ExtendsEditor(doc as MonoDevelop.Ide.Gui.Document, editor as IEditableTextBuffer):
		return IsUnityScriptFile(doc.Name)

	override def HandleCodeCompletion(context as CodeCompletionContext, completionChar as char):
#		print "HandleCodeCompletion(${context.ToString()}, ${completionChar.ToString()})"

		match completionChar.ToString():
			case ' ':
				lineText = GetLineText(context.TriggerLine).TrimStart()
				if not lineText.StartsWith("import "):
					return null

				return ImportCompletionDataFor('')

			case '.':
				lineText = GetLineText(context.TriggerLine)
				lineLength = lineText.Length
				lineText = lineText.TrimStart()
				trimmedLength = lineLength - lineText.Length
				if lineText.StartsWith("import "):
					nameSpace = lineText[len("import "):context.TriggerLineOffset-(2+trimmedLength)].Trim()
					return ImportCompletionDataFor(nameSpace)

				result = null as CompletionDataList
				text = string.Format ("{0}{1} {2}", Document.TextEditor.GetText (0, context.TriggerOffset),
				                                    CompletionFinder.CompletionToken,
				                                    Document.TextEditor.GetText (context.TriggerOffset, Document.TextEditor.TextLength))
				# print text
				_resolver.Input.Clear()
				_resolver.Input.Add(StringInput("completion text", text))

				ast = _resolver.Run()
				# print ast.ToCodeString()

				finder = CompletionFinder()
				type = finder.FindCompletionTypeFor(ast)
				# print type
				if (null != type):
					result = CompletionDataList()
					resultHash = Dictionary[of string,string]()
					for member in type.GetMembers():
						# print member
						resultHash[member.Name] = GetIconForMember(member)
					for pair in resultHash:
						result.Add(pair.Key, pair.Value)

				return result

			otherwise:
				return null

	def ImportCompletionDataFor(nameSpace as string):
#		print "ImportCompletionDataFor(${nameSpace})"

		result = CompletionDataList()
		for member in _dom.GetNamespaceContents(nameSpace, true, true):
			result.Add(member.Name, member.StockIcon)
		return result

	def GetLineText(line as int):
		return Document.TextEditor.GetLineText(line)

	def GetIconForMember(member as IEntity):
		if (EntityType.Method == member.EntityType):
			return Stock.Method
		elif (EntityType.Field == member.EntityType):
			return Stock.Field
		elif (EntityType.Property == member.EntityType):
			return Stock.Property
		elif (EntityType.Event == member.EntityType):
			return Stock.Event
		return Stock.Literal

namespace UnityScript.MonoDevelop.Completion

import System.Collections.Generic

import UnityScript
import UnityScript.MonoDevelop
import UnityScript.MonoDevelop.ProjectModel

import MonoDevelop.Core
import MonoDevelop.Projects
import MonoDevelop.Projects.Dom.Parser
import MonoDevelop.Ide.Gui
import MonoDevelop.Ide.Gui.Content
import MonoDevelop.Ide.CodeCompletion

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.PatternMatching

class UnityScriptEditorCompletion(CompletionTextEditorExtension):

	_dom as ProjectDom
	_resolver as UnityScriptTypeResolver
	_project as DotNetProject

	override def Initialize():
		super()
		_dom = ProjectDomService.GetProjectDom(Document.Project) or ProjectDomService.GetFileDom(Document.FileName)
		InstallUnityScriptSyntaxModeIfNeeded()
		_resolver = UnityScriptTypeResolver()
		_project = Document.Project as DotNetProject
		for reference in _project.References:
			if ReferenceType.Project != reference.ReferenceType:
				_resolver.AddReference(reference.Reference)

	def InstallUnityScriptSyntaxModeIfNeeded():
		view = Document.GetContent[of MonoDevelop.SourceEditor.SourceEditorView]()
		return if view is null

		mimeType = UnityScriptParser.MimeType
		return if view.Document.SyntaxMode.MimeType == mimeType

		mode = Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode(mimeType)
		if mode is not null:
			view.Document.SyntaxMode = mode
		else:
			LoggingService.LogWarning(GetType() + " could not get SyntaxMode for mimetype '" + mimeType + "'.")

	override def ExtendsEditor(doc as MonoDevelop.Ide.Gui.Document, editor as IEditableTextBuffer):
		return IsUnityScriptFile(doc.Name)

	override def HandleCodeCompletion(context as CodeCompletionContext, completionChar as char):
#		print "HandleCodeCompletion(${context.ToString()}, ${completionChar.ToString()})"

		match completionChar.ToString():
			case ' ':
				lineText = GetLineText(context.TriggerLine).TrimStart()
				if not lineText.StartsWith("import "):
					return null

				return ImportCompletionDataFor('')

			case '.':
				lineText = GetLineText(context.TriggerLine)
				lineLength = lineText.Length
				lineText = lineText.TrimStart()
				trimmedLength = lineLength - lineText.Length
				if lineText.StartsWith("import "):
					nameSpace = lineText[len("import "):context.TriggerLineOffset-(2+trimmedLength)].Trim()
					return ImportCompletionDataFor(nameSpace)

				result = null as CompletionDataList
				text = string.Format ("{0}{1} {2}", Document.TextEditor.GetText (0, context.TriggerOffset),
				                                    CompletionFinder.CompletionToken,
				                                    Document.TextEditor.GetText (context.TriggerOffset, Document.TextEditor.TextLength))
				# print text
				_resolver.Input.Clear()
				_resolver.Input.Add(StringInput("completion text", text))

				ast = _resolver.Run()
				# print ast.ToCodeString()

				finder = CompletionFinder()
				type = finder.FindCompletionTypeFor(ast)
				# print type
				if (null != type):
					result = CompletionDataList()
					resultHash = Dictionary[of string,string]()
					for member in type.GetMembers():
						# print member
						resultHash[member.Name] = GetIconForMember(member)
					for pair in resultHash:
						result.Add(pair.Key, pair.Value)

				return result

			otherwise:
				return null

	def ImportCompletionDataFor(nameSpace as string):
#		print "ImportCompletionDataFor(${nameSpace})"

		result = CompletionDataList()
		for member in _dom.GetNamespaceContents(nameSpace, true, true):
			result.Add(member.Name, member.StockIcon)
		return result

	def GetLineText(line as int):
		return Document.TextEditor.GetLineText(line)

	def GetIconForMember(member as IEntity):
		if (EntityType.Method == member.EntityType):
			return Stock.Method
		elif (EntityType.Field == member.EntityType):
			return Stock.Field
		elif (EntityType.Property == member.EntityType):
			return Stock.Property
		elif (EntityType.Event == member.EntityType):
			return Stock.Event
		return Stock.Literal


keep property getters in a single line when possible

namespace Boojay.Compilation.TypeSystem

import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Useful.Attributes

import java.util.jar

abstract class JarNamespaceCommon(AbstractNamespace):

	[getter(Jar)]
	_jar as JarFile

	_children = {}

	virtual FullName as string:
		get: return ""

	[once]
	override def GetMembers():
		return array(LoadMembers())

	private def LoadMembers() as IEntity*:
		entries = _jar.entries()
		while entries.hasMoreElements():
			entry as JarEntry = entries.nextElement()
			continue unless ShouldProcess(entry)

			relativeName = GetRelativeEntryName(entry)

			if HasNamespace(relativeName):
				yield ProcessNamespace(relativeName)
			else:
				yield JarClass(_jar, entry)

	virtual protected def ShouldProcess(entry as JarEntry):
		return true

	virtual protected def GetRelativeEntryName(entry as JarEntry):
		return entry.getName()

	private def HasNamespace(name as string):
		return "/" in name

	private def ProcessNamespace(name as string) as INamespace:
		return GetNamespace(/\//.Split(name)[0])

	private def GetNamespace(name as string):
		_children[name] = JarNamespace(FullName, _jar, name) unless _children.Contains(name)
		return _children[name]


when leaving the block exceptionally print the output to stdout

namespace Boojay.Compilation.Tests

import System.IO

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

import NUnit.Framework from nunit.framework

[TestFixture]
partial class JarIntergrationTest(CommonIntegrationTest):

	_assembly as Assembly

	override def compileTest(unit as CompileUnit):
		main = unit.Modules[0]
		main.Imports.Add([| import Boojay.Compilation.Tests |])

		compiler = newBooCompiler()
		compiler.Parameters.References.Add(typeof(CommonIntegrationTest).Assembly)
		compiler.Parameters.References.Add(typeof(Boo.Lang.Compiler.BooCompiler).Assembly)

		result = compiler.Run(unit)
		assert 0 == len(result.Errors), result.Errors.ToString(true) + unit.ToCodeString()

		_assembly = result.GeneratedAssembly

	override def runTest(main as Module):
		result = captureOutput:
			_assembly.EntryPoint.Invoke(null, (null,))
		return result

	private def captureOutput(block as callable):
		old = System.Console.Out
		writer = StringWriter()
		System.Console.SetOut(writer)

		try:
			block()
		except x:
			old.WriteLine(writer.ToString())
			raise
		ensure:
			System.Console.SetOut(old)

		return writer.ToString()

namespace Boojay.Compilation.Tests

import System.IO

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

import NUnit.Framework from nunit.framework

[TestFixture]
partial class JarIntergrationTest(CommonIntegrationTest):

	_assembly as Assembly

	override def compileTest(unit as CompileUnit):
		main = unit.Modules[0]
		main.Imports.Add([| import Boojay.Compilation.Tests |])

		compiler = newBooCompiler()
		compiler.Parameters.References.Add(typeof(CommonIntegrationTest).Assembly)
		compiler.Parameters.References.Add(typeof(Boo.Lang.Compiler.BooCompiler).Assembly)

		result = compiler.Run(unit)
		assert 0 == len(result.Errors), result.Errors.ToString(true) + unit.ToCodeString()

		_assembly = result.GeneratedAssembly

	override def runTest(main as Module):
		result = captureOutput:
			_assembly.EntryPoint.Invoke(null, (null,))

		return result

	private def captureOutput(block as callable):
		old = System.Console.Out
		writer = StringWriter()
		System.Console.SetOut(writer)

		try:
			block()
		ensure:
			System.Console.SetOut(old)

		return writer.ToString()


always keep the insert point visible

always keep the insert point visible

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@1442 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

import System
import Gtk from "gtk-sharp"
import Gdk from "gdk-sharp" as Gdk
import Pango from "pango-sharp" as Pango
import Boo.Lang.Interpreter from Boo.Lang.Interpreter

class PromptView(TextView):

	_interpreter = InteractiveInterpreter(RememberLastValue: true, Print: print)

	def constructor():

		self.WrapMode = Gtk.WrapMode.Word

		//if Environment.OSVersion.Platform in PlatformID.Win32NT, PlatformID.Win32Windows:
		self.ModifyFont(Pango.FontDescription(Family: "Lucida Console"))

		_interpreter.References.Add(typeof(TextView).Assembly)
		_interpreter.References.Add(typeof(Gdk.Key).Assembly)

		_interpreter.SetValue("cls", { Buffer.Text = "" })
		_interpreter.SetValue("view", self)

		prompt()

	override def OnKeyPressEvent(ev as Gdk.EventKey):
		if Gdk.Key.Return == ev.Key:
			try:
				EvalCurrentLine()
			except x:
				print(x)
			prompt()
			return true
		elif ev.Key in Gdk.Key.BackSpace, Gdk.Key.Left:
			if Buffer.GetIterAtMark(Buffer.InsertMark).LineOffset < 5:
				return true

		return super(ev)

	def print(obj):
		Buffer.InsertAtCursor("${obj}\n")

	def prompt():
		Buffer.MoveMark(Buffer.InsertMark, Buffer.EndIter)
		Buffer.InsertAtCursor(">>> ")
		ScrollMarkOnscreen(Buffer.InsertMark)

	def EvalCurrentLine():
		start = Buffer.GetIterAtLine(Buffer.LineCount)
		line = Buffer.GetText(start, Buffer.EndIter, false)

		print("")
		_interpreter.LoopEval(line[4:])

class MainWindow(Window):

	def constructor():
		super("booish")

		window = ScrolledWindow()
		window.Add(PromptView())

		self.Add(window)

		self.DeleteEvent += Application.Quit

Application.Init()

window = MainWindow(DefaultWidth:  400,
				DefaultHeight: 250)

window.ShowAll()

Application.Run()

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

import System
import Gtk from "gtk-sharp"
import Gdk from "gdk-sharp" as Gdk
import Pango from "pango-sharp" as Pango
import Boo.Lang.Interpreter from Boo.Lang.Interpreter

class PromptView(TextView):

	_interpreter = InteractiveInterpreter(RememberLastValue: true, Print: print)

	def constructor():

		self.WrapMode = Gtk.WrapMode.Word

		if Environment.OSVersion.Platform in PlatformID.Win32NT, PlatformID.Win32Windows:
			self.ModifyFont(
				Pango.FontDescription(Family: "Lucida Console", Size: 12))
		else:
			self.ModifyFont(
				Pango.FontDescription(Family: "Courier New"))

		_interpreter.References.Add(typeof(TextView).Assembly)
		_interpreter.References.Add(typeof(Gdk.Key).Assembly)

		_interpreter.SetValue("cls", { Buffer.Text = "" })

		prompt()

	override def OnKeyPressEvent(ev as Gdk.EventKey):
		if Gdk.Key.Return == ev.Key:
			try:
				EvalCurrentLine()
			except x:
				print(x)
			prompt()
			return true
		elif ev.Key in Gdk.Key.BackSpace, Gdk.Key.Left:
			if Buffer.GetIterAtMark(Buffer.InsertMark).LineOffset < 5:
				return true

		return super(ev)

	def print(obj):
		Buffer.InsertAtCursor("${obj}\n")

	def prompt():
		Buffer.MoveMark(Buffer.InsertMark, Buffer.EndIter)
		Buffer.InsertAtCursor(">>> ")

	def EvalCurrentLine():
		start = Buffer.GetIterAtLine(Buffer.LineCount)
		line = Buffer.GetText(start, Buffer.EndIter, false)

		print("")
		_interpreter.LoopEval(line[4:])

class MainWindow(Window):

	def constructor():
		super("booish")

		window = ScrolledWindow()
		window.Add(PromptView())

		self.Add(window)

		self.DeleteEvent += Application.Quit

Application.Init()

window = MainWindow(DefaultWidth:  400,
				DefaultHeight: 250)

window.ShowAll()

Application.Run()


document outline

document outline

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@770 2c1201b4-01cd-e047-a400-b836ae1fbc61

import System
import System.IO
import Boo.IO
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Ast
import Gdk from "gdk-sharp" as Gdk
import Gtk from "gtk-sharp"
import GtkSourceView from "gtksourceview-sharp"

class BooEditor(ScrolledWindow):

	static _booSourceLanguage = SourceLanguagesManager().GetLanguageFromMimeType("text/x-boo")

	[getter(Buffer)]
	_buffer = SourceBuffer(_booSourceLanguage,
							Highlight: true)

	_view = SourceView(_buffer,
						ShowLineNumbers: true,
						AutoIndent: true,
						TabsWidth: 4)

	[getter(FileName)]
	_fname as string

	Label:
		get:
			return System.IO.Path.GetFileName(_fname) if _fname
			return "unnamed.boo"

	def constructor():
		self.SetPolicy(PolicyType.Automatic, PolicyType.Automatic)
		self.Add(_view)

	def Open([required] fname as string):
		_buffer.Text = TextFile.ReadFile(fname)
		_buffer.Modified = false
		_fname = fname

	def SaveAs([required] fname as string):
		TextFile.WriteFile(fname, _buffer.Text)
		_fname = fname
		_buffer.Modified = false

	def Redo():
		_buffer.Redo()

	def Undo():
		_buffer.Undo()

class MainWindow(Window):

	_status = Statusbar(HasResizeGrip: false)
	_notebookEditors = Notebook(TabPos: PositionType.Top, Scrollable: true)
	_notebookHelpers = Notebook(TabPos: PositionType.Top, Scrollable: true)
	_notebookOutline = Notebook(TabPos: PositionType.Bottom, Scrollable: true)

	_documentOutline = TreeView()

	_accelGroup = AccelGroup()
	_editors = [] # workaround for gtk# bug #61703

	def constructor():
		super("Boo Explorer")

		self.AddAccelGroup(_accelGroup)
		self.Maximize()
		self.DeleteEvent += OnDelete

		_documentOutline.AppendColumn("Name", CellRendererText (), ("text", 0))
		sw = ScrolledWindow()
		sw.Add(_documentOutline)
		_notebookOutline.AppendPage(sw, Label("Document Outline"))

		vbox = VBox(false, 1)
		vbox.PackStart(CreateMenuBar(), false, false, 0)

		editPanel = VPaned()
		editPanel.Pack1(_notebookEditors, true, true)
		editPanel.Pack2(_notebookHelpers, false, true)

		mainPanel = HPaned()
		mainPanel.Pack2(_notebookOutline, false, false)
		mainPanel.Pack1(editPanel, true, true)

		vbox.PackStart(mainPanel, true, true, 0)
		vbox.PackStart(_status, false, false, 0)

		self.Add(vbox)

		self.NewDocument()

	private def AppendEditor(editor as BooEditor):
		_notebookEditors.AppendPage(editor, Label(editor.Label))
		_editors.Add(editor)
		editor.ShowAll()
		_notebookEditors.CurrentPage = _notebookEditors.NPages-1

	def NewDocument():
		self.AppendEditor(BooEditor())

	def OpenDocument(fname as string):
		editor = BooEditor()
		editor.Open(fname)
		self.AppendEditor(editor)

	private def CreateMenuBar():
		mb = MenuBar()

		file = Menu()
		file.Append(ImageMenuItem(Stock.New, _accelGroup, Activated: _menuItemNew_Activated))
		file.Append(ImageMenuItem(Stock.Open, _accelGroup, Activated: _menuItemOpen_Activated))
		file.Append(ImageMenuItem(Stock.Save, _accelGroup, Activated: _menuItemSave_Activated))
		file.Append(SeparatorMenuItem())
		file.Append(ImageMenuItem(Stock.Quit, _accelGroup, Activated: _menuItemExit_Activated))

		edit = Menu()
		edit.Append(ImageMenuItem(Stock.Undo, _accelGroup, Activated: _menuItemUndo_Activated))
		edit.Append(ImageMenuItem(Stock.Redo, _accelGroup, Activated: _menuItemRedo_Activated))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Cut, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Copy, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Paste, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Delete, _accelGroup))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Preferences, _accelGroup))

		tools = Menu()
		tools.Append(mi=ImageMenuItem(Stock.Execute, _accelGroup, Activated: _menuItemExecute_Activated))
		mi.AddAccelerator("activate", _accelGroup, AccelKey(Gdk.Key.F5, Enum.ToObject(Gdk.ModifierType, 0), AccelFlags.Visible))

		documents = Menu()
		documents.Append(ImageMenuItem(Stock.Close, _accelGroup))

		mb.Append(MenuItem("_File", Submenu: file))
		mb.Append(MenuItem("_Edit", Submenu: edit))
		mb.Append(MenuItem("_Tools", Submenu: tools))
		mb.Append(MenuItem("_Documents", Submenu: documents))
		return mb

	CurrentEditor as BooEditor:
		get:
			// can't do the simpler:
			// editor as BooEditor = _notebookEditors.CurrentPageWidget
			// because of gtk# bug #61703
			return _editors[_notebookEditors.CurrentPage]

	private def _menuItemExecute_Activated(sender, args as EventArgs):

		compiler = Boo.Lang.Compiler.BooCompiler()
		compiler.Parameters.Input.Add(
						StringInput(CurrentEditor.Label, 								CurrentEditor.Buffer.Text))
		compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.Run()

		result = compiler.Run()
		print(result.Errors.ToString()) if len(result.Errors)

	private def _menuItemNew_Activated(sender, args as EventArgs):
		self.NewDocument()

	private def _menuItemOpen_Activated(sender, args as EventArgs):
		fs = FileSelection("Open file", SelectMultiple: true)
		fs.Complete("*.boo")
		try:
			if cast(int, ResponseType.Ok) == fs.Run():
				for fname in fs.Selections:
					self.OpenDocument(fname)
		ensure:
			fs.Hide()

		self.UpdateDocumentOutline()

	private def UpdateDocumentOutline():
		DocumentOutlineProcessor(_documentOutline, CurrentEditor).Update()

	private def _menuItemSave_Activated(sender, args as EventArgs):
		editor = CurrentEditor
		fname = editor.FileName
		if fname is null:
			fs = FileSelection("Save As", SelectMultiple: false)
			if cast(int, ResponseType.Ok) != fs.Run():
				return
			fs.Hide()
			fname = fs.Selections[0]
		editor.SaveAs(fname)
		_notebookEditors.SetTabLabelText(editor, editor.Label)

	private def _menuItemUndo_Activated(sender, args as EventArgs):
		CurrentEditor.Undo()

	private def _menuItemRedo_Activated(sender, args as EventArgs):
		CurrentEditor.Redo()

	private def _menuItemExit_Activated(sender, args as EventArgs):
		Application.Quit()

	def OnDelete(sender, args as DeleteEventArgs):
		Application.Quit()
		args.RetVal = true

class DocumentOutlineProcessor:

	_store = TreeStore((string,))
	_documentOutline as TreeView
	_module as Boo.Lang.Compiler.Ast.Module

	def constructor(documentOutline, editor as BooEditor):
		_module = Parse(editor.FileName, editor.Buffer.Text)
		_documentOutline = documentOutline

	def Parse(fname, text):
		compiler = BooCompiler()
		compiler.Parameters.Input.Add(StringInput(fname, text))
		compiler.Parameters.Pipeline = Pipelines.Parse()
		return compiler.Run().CompileUnit.Modules[0]

	def Update():
		for type in _module.Members:
			iter = _store.AppendValues((type.Name,))
			if type isa TypeDefinition:
				UpdateType(iter, type)
		_documentOutline.Model = _store
		_documentOutline.ExpandAll()

	def UpdateType(parent, type as TypeDefinition):
		for member in type.Members:
			iter = _store.AppendValues(parent, (member.Name,))

Application.Init()

MainWindow().ShowAll()

Application.Run()

import System
import System.IO
import Boo.IO
import Gdk from "gdk-sharp" as Gdk
import Gtk from "gtk-sharp"
import GtkSourceView from "gtksourceview-sharp"

class BooEditor(ScrolledWindow):

	static _booSourceLanguage = SourceLanguagesManager().GetLanguageFromMimeType("text/x-boo")

	[getter(Buffer)]
	_buffer = SourceBuffer(_booSourceLanguage,
							Highlight: true)

	_view = SourceView(_buffer,
						ShowLineNumbers: true,
						AutoIndent: true,
						TabsWidth: 4)

	[getter(FileName)]
	_fname as string

	def constructor():
		self.SetPolicy(PolicyType.Automatic, PolicyType.Automatic)
		self.Add(_view)

	def Open([required] fname as string):
		_buffer.Text = TextFile.ReadFile(fname)
		_buffer.Modified = false
		_fname = fname

	def SaveAs([required] fname as string):
		TextFile.WriteFile(fname, _buffer.Text)
		_fname = fname
		_buffer.Modified = false

	def Redo():
		_buffer.Redo()

	def Undo():
		_buffer.Undo()

class MainWindow(Window):

	_status = Statusbar(HasResizeGrip: false)
	_notebookEditors = Notebook(TabPos: PositionType.Top, Scrollable: true)
	_notebookHelpers = Notebook(TabPos: PositionType.Top, Scrollable: true)
	_notebookOutline = Notebook(TabPos: PositionType.Bottom, Scrollable: true)
	_documentOutline = TreeView()
	_accelGroup = AccelGroup()
	_editors = [] # workaround for gtk# bug #61703

	def constructor():
		super("Boo Explorer")

		self.AddAccelGroup(_accelGroup)
		self.Maximize()
		self.DeleteEvent += OnDelete

		_notebookOutline.AppendPage(_documentOutline, Label("Document Outline"))

		vbox = VBox(false, 1)
		vbox.PackStart(CreateMenuBar(), false, false, 0)

		editPanel = VPaned()
		editPanel.Pack1(_notebookEditors, true, true)
		editPanel.Pack2(_notebookHelpers, false, true)

		mainPanel = HPaned()
		mainPanel.Pack2(_notebookOutline, false, false)
		mainPanel.Pack1(editPanel, true, true)

		vbox.PackStart(mainPanel, true, true, 0)
		vbox.PackStart(_status, false, false, 0)

		self.Add(vbox)

		self.NewDocument()

	private def AppendEditor(editor as BooEditor):
		label = editor.FileName or "unnamed.boo"
		_notebookEditors.AppendPage(editor, Label(label))
		_editors.Add(editor)
		editor.ShowAll()
		_notebookEditors.CurrentPage = _notebookEditors.NPages-1

	def NewDocument():
		self.AppendEditor(BooEditor())

	def OpenDocument(fname as string):
		editor = BooEditor()
		editor.Open(fname)
		self.AppendEditor(editor)

	private def CreateMenuBar():
		mb = MenuBar()

		file = Menu()
		file.Append(ImageMenuItem(Stock.New, _accelGroup, Activated: _menuItemNew_Activated))
		file.Append(ImageMenuItem(Stock.Open, _accelGroup, Activated: _menuItemOpen_Activated))
		file.Append(ImageMenuItem(Stock.Save, _accelGroup, Activated: _menuItemSave_Activated))
		file.Append(SeparatorMenuItem())
		file.Append(ImageMenuItem(Stock.Quit, _accelGroup, Activated: _menuItemExit_Activated))

		edit = Menu()
		edit.Append(ImageMenuItem(Stock.Undo, _accelGroup, Activated: _menuItemUndo_Activated))
		edit.Append(ImageMenuItem(Stock.Redo, _accelGroup, Activated: _menuItemRedo_Activated))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Cut, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Copy, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Paste, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Delete, _accelGroup))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Preferences, _accelGroup))

		tools = Menu()
		tools.Append(mi=ImageMenuItem(Stock.Execute, _accelGroup, Activated: _menuItemExecute_Activated))
		mi.AddAccelerator("activate", _accelGroup, AccelKey(Gdk.Key.F5, Enum.ToObject(Gdk.ModifierType, 0), AccelFlags.Visible))

		documents = Menu()
		documents.Append(ImageMenuItem(Stock.Close, _accelGroup))

		mb.Append(MenuItem("_File", Submenu: file))
		mb.Append(MenuItem("_Edit", Submenu: edit))
		mb.Append(MenuItem("_Tools", Submenu: tools))
		mb.Append(MenuItem("_Documents", Submenu: documents))
		return mb

	CurrentEditor as BooEditor:
		get:
			// can't do the simpler:
			// editor as BooEditor = _notebookEditors.CurrentPageWidget
			// because of gtk# bug #61703
			return _editors[_notebookEditors.CurrentPage]

	private def _menuItemExecute_Activated(sender, args as EventArgs):

		compiler = Boo.Lang.Compiler.BooCompiler()
		compiler.Parameters.Input.Add(
				Boo.Lang.Compiler.IO.StringInput(CurrentEditor.FileName or "unnamed.boo",
												CurrentEditor.Buffer.Text))
		compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.Run()

		result = compiler.Run()
		print(result.Errors.ToString()) if len(result.Errors)

	private def _menuItemNew_Activated(sender, args as EventArgs):
		self.NewDocument()

	private def _menuItemOpen_Activated(sender, args as EventArgs):
		fs = FileSelection("Open file", SelectMultiple: true)
		fs.Complete("*.boo")
		try:
			if cast(int, ResponseType.Ok) == fs.Run():
				for fname in fs.Selections:
					self.OpenDocument(fname)
		ensure:
			fs.Hide()

	private def _menuItemSave_Activated(sender, args as EventArgs):
		editor = CurrentEditor
		fname = editor.FileName
		if fname is null:
			fs = FileSelection("Save As", SelectMultiple: false)
			if cast(int, ResponseType.Ok) != fs.Run():
				return
			fs.Hide()
			fname = fs.Selections[0]
		editor.SaveAs(fname)
		_notebookEditors.SetTabLabelText(editor, editor.FileName)

	private def _menuItemUndo_Activated(sender, args as EventArgs):
		CurrentEditor.Undo()

	private def _menuItemRedo_Activated(sender, args as EventArgs):
		CurrentEditor.Redo()

	private def _menuItemExit_Activated(sender, args as EventArgs):
		Application.Quit()

	def OnDelete(sender, args as DeleteEventArgs):
		Application.Quit()
		args.RetVal = true

Application.Init()

MainWindow().ShowAll()

Application.Run()


minor change to example (Sum reads better than Add)

import Boo.Adt
import Boo.Lang.PatternMatching

data Expression = Const(value as int) \
	| Sum(left as Expression, right as Expression)

def eval(e as Expression) as int:
   match e:
      case Const(value):
      	return value
      case Sum(left, right):
      	return eval(left) + eval(right)

def simplify(e as Expression) as Expression:
	match e:
		case Sum(left: Const(value: 0), right):
			return simplify(right)
		case Sum(left, right: Const(value: 0)):
			return simplify(left)
		case Sum(left, right):
			return Sum(simplify(left), simplify(right))
		otherwise:
			return e

e = Sum(Sum(Const(19), Const(0)), Sum(Const(0), Const(23)))

print simplify(e)
print eval(e)
print eval(simplify(e))

import Boo.Lang.PatternMatching
import Boo.Adt

data Expression = Const(value as int) | Add(left as Expression, right as Expression)

def eval(e as Expression) as int:
   match e:
      case Const(value):
      	return value
      case Add(left, right):
      	return eval(left) + eval(right)

def simplify(e as Expression) as Expression:
	match e:
		case Add(left: Const(value: 0), right):
			return simplify(right)
		case Add(left, right: Const(value: 0)):
			return simplify(left)
		case Add(left, right):
			return Add(simplify(left), simplify(right))
		otherwise:
			return e

e = Add(Add(Const(19), Const(0)), Add(Const(0), Const(23)))

print simplify(e)
print eval(e)
print eval(simplify(e))


Fixed renaming algorithm for method overloads

namespace BooJs.Compiler.Steps

import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem(Ambiguous, Internal, EntityType)

class MethodOverloading(AbstractFastVisitorCompilerStep):
"""
Method overloading is performed by suffixing the original method name with a unique
identifier to ensure there are no name collisions in the generated javascript code.

    def foo(s as string):
    def foo(i as int):
    foo(10)
    ---
    def foo$0(s as string):
    def foo$1(i as int):
    foo$1(10)
"""
    def OnMethod(node as Method):
        cls = node.DeclaringType
        if not cls.ContainsAnnotation('method-overload-{0}' % node.Name):
            cls.Annotate('method-overload-{0}' % node.Name)
            overloads = [m for m in cls.Members if m.Name == node.Name]
            if len(overloads) > 1:
                # Create a new method with the original name to raise an error if called
                m = node.CloneNode()
                cls.Members.Insert(cls.Members.IndexOf(node), m)
                m.Parameters.Clear()
                m.Body.Clear()
                m.Body.Add([| raise 'Overloaded method' |])
                Visit m

                # Rename overloads to include a unique suffix
                for i, m in enumerate(overloads):
                    m.Name += '$' + i

        super(node)

    def OnMethodInvocationExpression(node as MethodInvocationExpression):
        return unless node.Target isa ReferenceExpression
        target = node.Target as ReferenceExpression
        ent = target.Entity as Internal.InternalMethod
        if ent:
            target.Name = ent.Name

namespace BooJs.Compiler.Steps

import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem(Ambiguous, Internal, EntityType)

class MethodOverloading(AbstractFastVisitorCompilerStep):
"""
Method overloading is performed by suffixing the original method name with a unique
identifier to ensure there are no name collisions in the generated javascript code.

    def foo(s as string):
    def foo(i as int):
    foo(10)
    ---
    def foo$0(s as string):
    def foo$1(i as int):
    foo$1(10)
"""
    def OnMethod(node as Method):
        cls = node.DeclaringType
        if not cls.ContainsAnnotation('method-overload-{0}' % node.Name):
            cls.Annotate('method-overload-{0}' % node.Name)
            type = NameResolutionService.Resolve(cls.Entity, node.Name, EntityType.Method)
            if type isa Boo.Lang.Compiler.TypeSystem.Ambiguous:
                # Create a new method with the original name to raise an error if called
                m = node.CloneNode()
                cls.Members.Insert(cls.Members.IndexOf(node), m)
                m.Parameters.Clear()
                m.Body.Clear()
                m.Body.Add([| raise 'Overloaded method' |])
                Visit m

                entities = (type as Ambiguous).Entities
                for i, entity as Internal.InternalMethod in enumerate(entities):
                    entity.Method.Name += '$' + i

        super(node)

    def OnMethodInvocationExpression(node as MethodInvocationExpression):
        return unless node.Target isa ReferenceExpression
        target = node.Target as ReferenceExpression
        ent = target.Entity as Internal.InternalMethod
        if ent:
            target.Name = ent.Name


match/case/otherwise is better than if/elif

namespace UnityScript.MonoDevelop.Completion

import System.Collections.Generic

import UnityScript
import UnityScript.MonoDevelop
import UnityScript.MonoDevelop.ProjectModel

import MonoDevelop.Core
import MonoDevelop.Projects
import MonoDevelop.Projects.Dom.Parser
import MonoDevelop.Ide.Gui
import MonoDevelop.Ide.Gui.Content
import MonoDevelop.Ide.CodeCompletion

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.PatternMatching

class UnityScriptEditorCompletion(CompletionTextEditorExtension):

	_dom as ProjectDom
	_resolver as UnityScriptTypeResolver
	_project as DotNetProject

	override def Initialize():
		super()
		_dom = ProjectDomService.GetProjectDom(Document.Project) or ProjectDomService.GetFileDom(Document.FileName)
		InstallUnityScriptSyntaxModeIfNeeded()
		_resolver = UnityScriptTypeResolver()
		_project = Document.Project as DotNetProject
		InitializeProjectReferences()

	def InitializeProjectReferences():
		if _project is null:
			return

		for reference in _project.References:
			if ReferenceType.Project != reference.ReferenceType:
				_resolver.AddReference(reference.Reference)

	def InstallUnityScriptSyntaxModeIfNeeded():
		view = Document.GetContent[of MonoDevelop.SourceEditor.SourceEditorView]()
		return if view is null

		mimeType = UnityScriptParser.MimeType
		return if view.Document.SyntaxMode.MimeType == mimeType

		mode = Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode(mimeType)
		if mode is not null:
			view.Document.SyntaxMode = mode
		else:
			LoggingService.LogWarning(GetType() + " could not get SyntaxMode for mimetype '" + mimeType + "'.")

	override def ExtendsEditor(doc as MonoDevelop.Ide.Gui.Document, editor as IEditableTextBuffer):
		return IsUnityScriptFile(doc.Name)

	override def HandleCodeCompletion(context as CodeCompletionContext, completionChar as char):
#		print "HandleCodeCompletion(${context.ToString()}, ${completionChar.ToString()})"

		match completionChar.ToString():
			case ' ':
				lineText = GetLineText(context.TriggerLine).TrimStart()
				if not lineText.StartsWith("import "):
					return null

				return ImportCompletionDataFor('')

			case '.':
				lineText = GetLineText(context.TriggerLine)
				lineLength = lineText.Length
				lineText = lineText.TrimStart()
				trimmedLength = lineLength - lineText.Length
				if lineText.StartsWith("import "):
					nameSpace = lineText[len("import "):context.TriggerLineOffset-(2+trimmedLength)].Trim()
					return ImportCompletionDataFor(nameSpace)

				result = null as CompletionDataList
				text = string.Format ("{0}{1} {2}", Document.TextEditor.GetText (0, context.TriggerOffset),
				                                    CompletionFinder.CompletionToken,
				                                    Document.TextEditor.GetText (context.TriggerOffset, Document.TextEditor.TextLength))
				# print text
				_resolver.Input.Clear()
				_resolver.Input.Add(StringInput("completion text", text))

				ast = _resolver.Run()
				# print ast.ToCodeString()

				finder = CompletionFinder()
				type = finder.FindCompletionTypeFor(ast)
				# print type
				if (null != type):
					result = CompletionDataList()
					resultHash = Dictionary[of string,string]()
					for member in type.GetMembers():
						# print member
						resultHash[member.Name] = GetIconForMember(member)
					for pair in resultHash:
						result.Add(pair.Key, pair.Value)

				return result

			otherwise:
				return null

	def ImportCompletionDataFor(nameSpace as string):
#		print "ImportCompletionDataFor(${nameSpace})"

		result = CompletionDataList()
		for member in _dom.GetNamespaceContents(nameSpace, true, true):
			result.Add(member.Name, member.StockIcon)
		return result

	def GetLineText(line as int):
		return Document.TextEditor.GetLineText(line)

	def GetIconForMember(member as IEntity):
		match member.EntityType:
			case EntityType.Method:
				return Stock.Method
			case EntityType.Field:
				return Stock.Field
			case EntityType.Property:
				return Stock.Property
			case EntityType.Event:
				return Stock.Event
			otherwise:
				return Stock.Literal

namespace UnityScript.MonoDevelop.Completion

import System.Collections.Generic

import UnityScript
import UnityScript.MonoDevelop
import UnityScript.MonoDevelop.ProjectModel

import MonoDevelop.Core
import MonoDevelop.Projects
import MonoDevelop.Projects.Dom.Parser
import MonoDevelop.Ide.Gui
import MonoDevelop.Ide.Gui.Content
import MonoDevelop.Ide.CodeCompletion

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.PatternMatching

class UnityScriptEditorCompletion(CompletionTextEditorExtension):

	_dom as ProjectDom
	_resolver as UnityScriptTypeResolver
	_project as DotNetProject

	override def Initialize():
		super()
		_dom = ProjectDomService.GetProjectDom(Document.Project) or ProjectDomService.GetFileDom(Document.FileName)
		InstallUnityScriptSyntaxModeIfNeeded()
		_resolver = UnityScriptTypeResolver()
		_project = Document.Project as DotNetProject
		InitializeProjectReferences()

	def InitializeProjectReferences():
		if _project is null:
			return

		for reference in _project.References:
			if ReferenceType.Project != reference.ReferenceType:
				_resolver.AddReference(reference.Reference)

	def InstallUnityScriptSyntaxModeIfNeeded():
		view = Document.GetContent[of MonoDevelop.SourceEditor.SourceEditorView]()
		return if view is null

		mimeType = UnityScriptParser.MimeType
		return if view.Document.SyntaxMode.MimeType == mimeType

		mode = Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode(mimeType)
		if mode is not null:
			view.Document.SyntaxMode = mode
		else:
			LoggingService.LogWarning(GetType() + " could not get SyntaxMode for mimetype '" + mimeType + "'.")

	override def ExtendsEditor(doc as MonoDevelop.Ide.Gui.Document, editor as IEditableTextBuffer):
		return IsUnityScriptFile(doc.Name)

	override def HandleCodeCompletion(context as CodeCompletionContext, completionChar as char):
#		print "HandleCodeCompletion(${context.ToString()}, ${completionChar.ToString()})"

		match completionChar.ToString():
			case ' ':
				lineText = GetLineText(context.TriggerLine).TrimStart()
				if not lineText.StartsWith("import "):
					return null

				return ImportCompletionDataFor('')

			case '.':
				lineText = GetLineText(context.TriggerLine)
				lineLength = lineText.Length
				lineText = lineText.TrimStart()
				trimmedLength = lineLength - lineText.Length
				if lineText.StartsWith("import "):
					nameSpace = lineText[len("import "):context.TriggerLineOffset-(2+trimmedLength)].Trim()
					return ImportCompletionDataFor(nameSpace)

				result = null as CompletionDataList
				text = string.Format ("{0}{1} {2}", Document.TextEditor.GetText (0, context.TriggerOffset),
				                                    CompletionFinder.CompletionToken,
				                                    Document.TextEditor.GetText (context.TriggerOffset, Document.TextEditor.TextLength))
				# print text
				_resolver.Input.Clear()
				_resolver.Input.Add(StringInput("completion text", text))

				ast = _resolver.Run()
				# print ast.ToCodeString()

				finder = CompletionFinder()
				type = finder.FindCompletionTypeFor(ast)
				# print type
				if (null != type):
					result = CompletionDataList()
					resultHash = Dictionary[of string,string]()
					for member in type.GetMembers():
						# print member
						resultHash[member.Name] = GetIconForMember(member)
					for pair in resultHash:
						result.Add(pair.Key, pair.Value)

				return result

			otherwise:
				return null

	def ImportCompletionDataFor(nameSpace as string):
#		print "ImportCompletionDataFor(${nameSpace})"

		result = CompletionDataList()
		for member in _dom.GetNamespaceContents(nameSpace, true, true):
			result.Add(member.Name, member.StockIcon)
		return result

	def GetLineText(line as int):
		return Document.TextEditor.GetLineText(line)

	def GetIconForMember(member as IEntity):
		if (EntityType.Method == member.EntityType):
			return Stock.Method
		elif (EntityType.Field == member.EntityType):
			return Stock.Field
		elif (EntityType.Property == member.EntityType):
			return Stock.Property
		elif (EntityType.Event == member.EntityType):
			return Stock.Event
		return Stock.Literal


little refactoring to remove code duplication

namespace Boojay.Compilation.Tests

import System.IO
import NUnit.Framework

import Boo.Lang.Compiler.Ast

import Boojay.Compilation
import Boojay.Compilation.TypeSystem

[TestFixture]
class UtilsTest(TestWithCompilerContext):

	[Test] def SimpleCompile():
		simpleCompileTest = [|
			import java.lang

			class Foo:
				pass
		|]

		RemoveClasses(simpleCompileTest)

		boojayCompile(CompileUnit(simpleCompileTest))

		Assert.AreEqual(1, len(simpleCompileTest.Members))

		AssertClassesGeneration(simpleCompileTest)

	[Test] def CompileWithJars():
		compileWithJarsTest = [|
			import java.lang

			class Foo:
				def getBarName():
					Bar().getName()
		|]

		library = [|
			import java.lang

			class Bar:
				def getName():
					return "Bar"
		|]

		generatedJar = generateTempJarWith(library)
		jarCompileUnit = JarTypeSystemProvider().ForJar(generatedJar)

		RemoveClasses(compileWithJarsTest)

		boojayCompile(CompileUnit(compileWithJarsTest), jarCompileUnit)

		Assert.AreEqual(1, len(compileWithJarsTest.Members))

		AssertClassesGeneration(compileWithJarsTest)

	private def RemoveClasses(unit as Module):
		for type in unit.Members:
			className = "${type.FullName.Replace('.', '/')}.class"
			File.Delete(className) if File.Exists(className)

	private def AssertClassesGeneration(unit as Module):
		for type in unit.Members:
			className = "${type.FullName.Replace('.', '/')}.class"
			Assert.IsTrue(File.Exists(className), "File does not exists: ${className}")

namespace Boojay.Compilation.Tests

import System.IO
import NUnit.Framework

import Boo.Lang.Compiler.Ast

import Boojay.Compilation
import Boojay.Compilation.TypeSystem

[TestFixture]
class UtilsTest(TestWithCompilerContext):

	[Test] def SimpleCompile():
		simpleCompileTest = [|
			import java.lang

			class Foo:
				pass
		|]

		for type in simpleCompileTest.Members:
			className = "${type.FullName.Replace('.', '/')}.class"
			File.Delete(className) if File.Exists(className)

		boojayCompile(CompileUnit(simpleCompileTest))

		Assert.AreEqual(1, len(simpleCompileTest.Members))

		for type in simpleCompileTest.Members:
			className = "${type.FullName.Replace('.', '/')}.class"
			Assert.IsTrue(File.Exists(className), "File does not exists: ${className}")

	[Test] def CompileWithJars():
		compileWithJarsTest = [|
			import java.lang

			class Foo:
				def getBarName():
					Bar().getName()
		|]

		library = [|
			import java.lang

			class Bar:
				def getName():
					return "Bar"
		|]

		generatedJar = generateTempJarWith(library)
		jarCompileUnit = JarTypeSystemProvider().ForJar(generatedJar)

		for type in compileWithJarsTest.Members:
			className = "${type.FullName.Replace('.', '/')}.class"
			File.Delete(className) if File.Exists(className)

		boojayCompile(CompileUnit(compileWithJarsTest), jarCompileUnit)

		Assert.AreEqual(1, len(compileWithJarsTest.Members))

		for type in compileWithJarsTest.Members:
			className = "${type.FullName.Replace('.', '/')}.class"
			Assert.IsTrue(File.Exists(className), "File does not exists: ${className}")


camelCase => PascalCase

camelCase => PascalCase

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@1845 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.Lang.Useful.Attributes

import System.Threading
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem

class OnceAttribute(AbstractAstAttribute):
"""
Caches the return value of a method.

@author Sorin Ionescu (sorin.ionescu@gmail.com)
"""
	private class ReturnValueStorageVisitor(DepthFirstVisitor):
	"""
	Replaces returns statements with binary expressions that
	store the values of the return statements.
	"""
		_returnValue as ReferenceExpression

		def constructor(returnValue as ReferenceExpression):
			_returnValue = returnValue

		override def OnReturnStatement(returnStatement as ReturnStatement):
		"""
		Replaces returns statements with binary expressions that
		store the values of the return statements.
		"""
			returnValueAssignment = BinaryExpression(
				LexicalInfo: returnStatement.LexicalInfo,
				Operator: BinaryOperatorType.Assign,
				Left: _returnValue,
				Right: returnStatement.Expression)

			parentNode = returnStatement.ParentNode
			parentNode.Replace(
				returnStatement,
				ExpressionStatement(returnValueAssignment))

	_method as Method
	_methodLock as Field
	_cached as Field
	_returnValue as Field

	override def Dispose():
	"""
	Dont get rid of the context because we'll need it later.
	"""
		pass

	override def Apply(node as Node):
	"""
	Applies the <OnceAttribute> to [node].

	Parameters:
		node
			The node to apply the <OnceAttribute> to.
	"""
		assert node isa Method

		_method = node

		CreateCachedField()
		CreateMethodLockField()
		PrepareMethodBody()

		Context.Parameters.Pipeline.AfterStep += def(
			sender,
			e as CompilerStepEventArgs):

			return if not e.Step isa ProcessMethodBodies

			# Void methods cannot be cached.
			assert _method.ReturnType.Entity is not \
				self.TypeSystemServices.VoidType, "once attribute cannot be applied to void methods"

			CreateReturnValueField()
			PostProcessMethod()

	def CreateReturnValueField():
	"""
	Creates the field that stores the return value of the cached method.
	"""
		template = self.CodeBuilder.CreateField('field', _method.ReturnType.Entity)
		_returnValue = AddField(template, "___${_method.Name}_returnValue")

	def CreateCachedField():
	"""
	Creates the cached flag.

	Remarks:
		The flag is used to check whether the method has been cached.
	"""
		template = ast:
			private field as bool
		_cached = AddField(template, "___${_method.Name}_cached")

	def CreateMethodLockField():
	"""
	Creates the lock field.

	Remarks:
		The field is used to lock on when the operatation is thread safe.
	"""
		template = ast:
			private field as object = object()
		_methodLock = AddField(template, "___${_method.Name}_lock")

	def AddField(template as Field, name as string):
		template.LexicalInfo = self.LexicalInfo
		template.Name = name
		template.Modifiers = TypeMemberModifiers.Private
		template.Modifiers |= TypeMemberModifiers.Static if IsStaticMethod()
		_method.DeclaringType.Members.Add(template)
		return template

	def IsStaticMethod():
		return _method.IsStatic or _method.ParentNode isa Module

	def PrepareMethodBody():
		newMethodBodyTemplate = ast:
			if not cached:
				System.Threading.Monitor.Enter(methodLock)
				try:
					if not cached:
						oldMethodBody
						cached = true
				ensure:
					System.Threading.Monitor.Exit(methodLock)

		ReplaceReferences(newMethodBodyTemplate, 'cached', _cached.Name)
		ReplaceReferences(newMethodBodyTemplate, 'methodLock', _methodLock.Name)
		newMethodBodyTemplate.ReplaceNodes(
			MacroStatement(Name: 'oldMethodBody'),
			_method.Body)

		_method.Body = Block()
		_method.Body.Add(newMethodBodyTemplate)

	def ReplaceReferences(node as Node, what as string, value as string):
		node.ReplaceNodes(
			ReferenceExpression(what),
			ReferenceExpression(value))

	def PostProcessMethod():
	"""
	Visit the node and replace return statements
	with binary expressions that store the return
	statement values.
	Add a single return statement at the end
	to return the cached value.
	"""
		_method.Accept(
				ReturnValueStorageVisitor(
					self.CodeBuilder.CreateReference(_returnValue)))
		_method.Body.Add(
			ReturnStatement(
				LexicalInfo: LexicalInfo,
				Expression: self.CodeBuilder.CreateReference(_returnValue)))

#region license
// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.Lang.Useful.Attributes

import System.Threading
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem

class OnceAttribute(AbstractAstAttribute):
"""
Caches the return value of a method.

@author Sorin Ionescu (sorin.ionescu@gmail.com)
"""
	private class ReturnValueStorageVisitor(DepthFirstVisitor):
	"""
	Replaces returns statements with binary expressions that
	store the values of the return statements.
	"""
		_returnValue as ReferenceExpression

		def constructor(returnValue as ReferenceExpression):
			_returnValue = returnValue

		override def OnReturnStatement(returnStatement as ReturnStatement):
		"""
		Replaces returns statements with binary expressions that
		store the values of the return statements.
		"""
			returnValueAssignment = BinaryExpression(
				LexicalInfo: returnStatement.LexicalInfo,
				Operator: BinaryOperatorType.Assign,
				Left: _returnValue,
				Right: returnStatement.Expression)

			parentNode = returnStatement.ParentNode
			parentNode.Replace(
				returnStatement,
				ExpressionStatement(returnValueAssignment))

	_method as Method
	_methodLock as Field
	_cached as Field
	_returnValue as Field

	override def Dispose():
	"""
	Dont get rid of the context because we'll need it later.
	"""
		pass

	override def Apply(node as Node):
	"""
	Applies the <OnceAttribute> to [node].

	Parameters:
		node
			The node to apply the <OnceAttribute> to.
	"""
		assert node isa Method

		_method = node

		CreateCachedField()
		CreateMethodLockField()
		PrepareMethodBody()

		Context.Parameters.Pipeline.AfterStep += def(
			sender,
			e as CompilerStepEventArgs):

			return if not e.Step isa ProcessMethodBodies

			# Void methods cannot be cached.
			assert _method.ReturnType.Entity is not \
				self.TypeSystemServices.VoidType, "once attribute cannot be applied to void methods"

			CreateReturnValueField()
			PostProcessMethod()

	def CreateReturnValueField():
	"""
	Creates the field that stores the return value of the cached method.
	"""
		template = self.CodeBuilder.CreateField('field', _method.ReturnType.Entity)
		_returnValue = AddField(template, "___${_method.Name}_returnValue")

	def CreateCachedField():
	"""
	Creates the cached flag.

	Remarks:
		The flag is used to check whether the method has been cached.
	"""
		template = ast:
			private field as bool
		_cached = AddField(template, "___${_method.Name}_cached")

	def CreateMethodLockField():
	"""
	Creates the lock field.

	Remarks:
		The field is used to lock on when the operatation is thread safe.
	"""
		template = ast:
			private field as object = object()
		_methodLock = AddField(template, "___${_method.Name}_lock")

	def AddField(template as Field, name as string):
		template.LexicalInfo = self.LexicalInfo
		template.Name = name
		template.Modifiers = TypeMemberModifiers.Private
		template.Modifiers |= TypeMemberModifiers.Static if IsStaticMethod()
		_method.DeclaringType.Members.Add(template)
		return template

	def IsStaticMethod():
		return _method.IsStatic or _method.ParentNode isa Module

	def PrepareMethodBody():
		newMethodBodyTemplate = ast:
			if not cached:
				System.Threading.Monitor.Enter(methodLock)
				try:
					if not cached:
						oldMethodBody
						cached = true
				ensure:
					System.Threading.Monitor.Exit(methodLock)

		replaceReferences(newMethodBodyTemplate, 'cached', _cached.Name)
		replaceReferences(newMethodBodyTemplate, 'methodLock', _methodLock.Name)
		newMethodBodyTemplate.ReplaceNodes(
			MacroStatement(Name: 'oldMethodBody'),
			_method.Body)

		_method.Body = Block()
		_method.Body.Add(newMethodBodyTemplate)

	def replaceReferences(node as Node, what as string, value as string):
		node.ReplaceNodes(
			ReferenceExpression(what),
			ReferenceExpression(value))

	def PostProcessMethod():
	"""
	Visit the node and replace return statements
	with binary expressions that store the return
	statement values.
	Add a single return statement at the end
	to return the cached value.
	"""
		_method.Accept(
				ReturnValueStorageVisitor(
					self.CodeBuilder.CreateReference(_returnValue)))
		_method.Body.Add(
			ReturnStatement(
				LexicalInfo: LexicalInfo,
				Expression: self.CodeBuilder.CreateReference(_returnValue)))


Fixed isFactory helper

Fixed isFactory helper

namespace BooJs.Compiler.Utils

import Boo.Lang.Compiler
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Services
import Boo.Lang.Compiler.Ast

import Boo.Lang.Environments
import Boo.Lang.PatternMatching

import BooJs.Lang.Extensions(ExternAttribute)

def isExtern(node as Node):
    entity = node.Entity as Reflection.ExternalType
    return false if not entity
    return isExtern(entity.ActualType)

def isExtern(fqn as string):
    srv = my(NameResolutionService)
    entity = srv.ResolveQualifiedName(fqn) as Reflection.ExternalType
    return false if not entity
    return isExtern(entity.ActualType)

def isExtern(info as System.Reflection.MemberInfo):
    attr = System.Attribute.GetCustomAttribute(info, typeof(BooJs.Lang.Extensions.ExternAttribute), false)
    return attr is not null

def isFactory(node as Node):
    match node.Entity:
        case it=Internal.InternalConstructor():
            # TODO: Obtain attribute from internal type
            return false
        case et=Reflection.ExternalType():
            attr as ExternAttribute = System.Attribute.GetCustomAttribute(et.ActualType, typeof(ExternAttribute), false)
            return (attr.Factory if attr else false)
        otherwise:
            return false

def resolveRuntimeMethod(methodName as string):
    return resolveMethod(typeSystem().RuntimeServicesType, methodName)

def resolveMethod(type as IType, name as string):
    return nameResolutionService().ResolveMethod(type, name)

def bindingFor(node as Node):
    return typeSystem().GetEntity(node)

def bindingFor(node as Method) as IMethod:
    return typeSystem().GetEntity(node)

def erasureFor(type as IType):
    if type isa IGenericParameter:
        return typeSystem().ObjectType

    #genericInstance = type.ConstructedInfo
    #if genericInstance is not null:
    #   return genericInstance.GenericDefinition

    return type

def definitionFor(m as IMethodBase) as IMethodBase:
    if m.DeclaringType.ConstructedInfo is null:
        return m
    # TODO: What do we need this for
    #return Boojs.Compilation.TypeSystem.GenericMethodDefinitionFinder(m).find()
    raise 'GenericMethodDefinitionFinder not implemented'

def typeOf(e as Expression) as IType:
    match e:
        case [| null |]:
            return Null.Default
        case [| true |] | [| false |]:
            return typeSystem().BoolType
        otherwise:
            return typeSystem().GetExpressionType(e)

def typeSystem():
    return my(TypeSystemServices)

def nameResolutionService():
    return my(NameResolutionService)

def context():
    return CompilerContext.Current

def uniqueName():
    return context().GetUniqueName("$")

def uniqueReference():
    return ReferenceExpression(uniqueName())

namespace BooJs.Compiler.Utils

import Boo.Lang.Compiler
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Services
import Boo.Lang.Compiler.Ast

import Boo.Lang.Environments
import Boo.Lang.PatternMatching

import BooJs.Lang.Extensions(ExternAttribute)

def isExtern(node as Node):
    entity = node.Entity as Reflection.ExternalType
    return false if not entity
    return isExtern(entity.ActualType)

def isExtern(fqn as string):
    srv = my(NameResolutionService)
    entity = srv.ResolveQualifiedName(fqn) as Reflection.ExternalType
    return false if not entity
    return isExtern(entity.ActualType)

def isExtern(info as System.Reflection.MemberInfo):
    attr = System.Attribute.GetCustomAttribute(info, typeof(BooJs.Lang.Extensions.ExternAttribute), false)
    return attr is not null

def isFactory(node as Node):
    entity = node.Entity as Reflection.ExternalType
    if not entity and node.Entity isa IConstructor:
        entity = (node.Entity as IConstructor).DeclaringType

    return false if not entity

    attr as ExternAttribute = System.Attribute.GetCustomAttribute(entity.ActualType, typeof(ExternAttribute), false)
    return (attr.Factory if attr else false)

def resolveRuntimeMethod(methodName as string):
    return resolveMethod(typeSystem().RuntimeServicesType, methodName)

def resolveMethod(type as IType, name as string):
    return nameResolutionService().ResolveMethod(type, name)

def bindingFor(node as Node):
    return typeSystem().GetEntity(node)

def bindingFor(node as Method) as IMethod:
    return typeSystem().GetEntity(node)

def erasureFor(type as IType):
    if type isa IGenericParameter:
        return typeSystem().ObjectType

    #genericInstance = type.ConstructedInfo
    #if genericInstance is not null:
    #   return genericInstance.GenericDefinition

    return type

def definitionFor(m as IMethodBase) as IMethodBase:
    if m.DeclaringType.ConstructedInfo is null:
        return m
    # TODO: What do we need this for
    #return Boojs.Compilation.TypeSystem.GenericMethodDefinitionFinder(m).find()
    raise 'GenericMethodDefinitionFinder not implemented'

def typeOf(e as Expression) as IType:
    match e:
        case [| null |]:
            return Null.Default
        case [| true |] | [| false |]:
            return typeSystem().BoolType
        otherwise:
            return typeSystem().GetExpressionType(e)

def typeSystem():
    return my(TypeSystemServices)

def nameResolutionService():
    return my(NameResolutionService)

def context():
    return CompilerContext.Current

def uniqueName():
    return context().GetUniqueName("$")

def uniqueReference():
    return ReferenceExpression(uniqueName())


better formating

better formating

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@787 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// boo - an extensible programming language for the CLI
// Copyright (C) 2004 Rodrigo Barreto de Oliveira
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Contact Information
//
// mailto:rbo@acm.org
#endregion

namespace Boo.NAnt

import System
import System.Diagnostics
import System.IO
import NAnt.Core
import NAnt.Core.Attributes
import NAnt.Core.Types
import Boo.Lang.Compiler

abstract class AbstractBooTask(Task):

	def constructor():
		baseAssemblyFolder = Path.GetDirectoryName(GetType().Assembly.Location)
		System.Reflection.Assembly.LoadFrom(
			Path.Combine(baseAssemblyFolder, "Boo.AntlrParser.dll"))

	protected def RunCompiler(compiler as BooCompiler):
		result = compiler.Run()
		CheckCompilationResult(result)
		return result

	protected def CheckCompilationResult(context as CompilerContext):
		errors = context.Errors
		verbose = context.Parameters.TraceSwitch.TraceInfo
		for error in errors:
			LogError(error.ToString(verbose))

		if len(errors):
			LogInfo("${len(errors)} error(s).")
			raise BuildException("boo compilation error", Location)

	def GetFrameworkDirectory():
		return Project.TargetFramework.FrameworkAssemblyDirectory.ToString()

	def print(message):
		LogVerbose(message)

	def LogInfo(message):
		self.Log(Level.Info, "${LogPrefix}${message}")

	def LogVerbose(message):
		self.Log(Level.Verbose, "${LogPrefix}${message}")

	def LogError(message):
		self.Log(Level.Error, "${LogPrefix}${message}")

#region license
// boo - an extensible programming language for the CLI
// Copyright (C) 2004 Rodrigo Barreto de Oliveira
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Contact Information
//
// mailto:rbo@acm.org
#endregion

namespace Boo.NAnt

import System
import System.Diagnostics
import System.IO
import NAnt.Core
import NAnt.Core.Attributes
import NAnt.Core.Types
import Boo.Lang.Compiler

abstract class AbstractBooTask(Task):

	def constructor():
		baseAssemblyFolder = Path.GetDirectoryName(GetType().Assembly.Location)
		System.Reflection.Assembly.LoadFrom(Path.Combine(baseAssemblyFolder, "Boo.AntlrParser.dll"))

	protected def RunCompiler(compiler as BooCompiler):

		result = compiler.Run()
		CheckCompilationResult(result)
		return result

	protected def CheckCompilationResult(context as CompilerContext):
		errors = context.Errors
		verbose = context.Parameters.TraceSwitch.TraceInfo
		for error in errors:
			LogError(error.ToString(verbose))

		if len(errors):
			LogInfo("${len(errors)} error(s).")
			raise BuildException("boo compilation error", Location)

	def GetFrameworkDirectory():
		return Project.TargetFramework.FrameworkAssemblyDirectory.ToString()

	def print(message):
		LogVerbose(message)

	def LogInfo(message):
		self.Log(Level.Info, "${LogPrefix}${message}")

	def LogVerbose(message):
		self.Log(Level.Verbose, "${LogPrefix}${message}")

	def LogError(message):
		self.Log(Level.Error, "${LogPrefix}${message}")