Using Eiffel ENViSioN! for .NET development

1. Introduction

Eiffel Envision is a "plugin" for MS Visual Studio. It makes .NET applications from Eiffel code. Latest version 2.0 supports MS VS 2003. You can download free version here.

Discuss Envision at Eiffel Software User list Yahoo group. Send bug reports via this form.

2. Envision specifics

2.1. Build

1. Don't hesitate to Rebuild your project when something looks suspicious.
2. If your unmanaged C compilation doesn't work at all, run vsvars32.bat before VS.
3. Watch for cec.exe processes. If you have Build problems and number of cec.exe processes is more than 3, I recommend to kill them.
4. Don't use any files in debug/release directories during Rebuild process.

2.2. Name mangling

Envision mangles all .NET names (e.g. TestFixture -> TEST_FIXTURE_ATTRIBUTE). Use Object Browser - References to discover name mapping. It also has Find Symbol search facility.

2.3. Precompile

By default your project uses precompile library from $ISE_EIFFEL\ebcl\v1.1.4322. It adds ebcl11.dll (23 MB) file to your distribution.

To make your own precompile library:

1. Create new Eiffel Class Library Project.
2. (There is supposed to be a wizard, but I don't see it.)
3. In standard Project Properties set "Output Type" to Precompile Library, set "Precompiled Library Path" to empty, Remove unused "Clusters" (I use only base and base_net and my eiffel_precompile.dll is only 2.2 MB in size).
4. In your main project in "Precompiled Library Path" browse to equivalent of e:\programming\eiffel_precompile\obj\Release\precomp.epr for your system.

2.4. No assertions in "standard" classes

Be aware that this doesn't throw
feature make is
        local
                 d : ARRAYED_LIST[INTEGER]
        do
                 create d.make(-1)
        end

2.5. Multiple attributes

Separate each attribute with comma:
feature test is
   indexing
      metadata: create {IGNORE_ATTRIBUTE}.make("testing") end, create {TEST_ATTRIBUTE}.make end
   do
   end

2.6. No support for expanded classes

-- e_class.e:
expanded class
        E_CLASS

feature value : INTEGER

end

-- root_class.e:
class
        ROOT_CLASS

creation
        make

feature make is
        local
            e : E_CLASS
            i : INTEGER
        do
            i := e.value
       end
end
It throws System.NullReferenceException.

3. NUnit

NUnit testing framework supports all .NET applications and you can use it with Envision.

3.1. Quick start

1. Add nunit.framework.dll to project Assembly References.
2. Create test class:
indexing
     class_metadata: create {TEST_FIXTURE_ATTRIBUTE}.make end

class
     TEST_CLASS
3. Create test function in this class:
feature test_function is
     indexing
        metadata: create {TEST_ATTRIBUTE}.make end 
     do
     end
4. Add reference to test class from the main code:
feature make is
   local
       dummy : TEST_CLASS -- explicit reference to test

3.2. Assertions

Pre-conditions, post-conditions, checks and invariants need to be "turned on" to work. You set them to Evaluate in project options, but they also need to be initialized in run time. When you run your app as exe - startup code initializes them, but when NUnit runs test functions - no initialization occurs. To "turn on" assertions for tests add to your root test class this code:

feature {NONE} turn_on_assertions is
		indexing
			metadata: create {TEST_FIXTURE_SET_UP_ATTRIBUTE}.make end
		do
			feature {ISE_RUNTIME}.initialize_assertions(Current.get_type.type_handle)	
			custom_fixture_setup
		end

4. Code formatter

Envision doesn't automatically indent your code and here is a solution to this problem using Emacs. It requires plenty of wrappers, but finally works as well as standard formatting in VS for C++ and C#.

This archive contains all my files described below.

4.1. Install Emacs

You can download Emacs for Win32 (emacs-21.3-w32.zip) from here. Just unzip it any place you like.

4.2. Install eiffel.el

Martin Schwenke maintains Eiffel code formatter library (eiffel.el) for Emacs on this page. It misses some Envision features (in v 2.67) like static calls:
  if not stopping.get then
     feature {THREAD}.sleep_integer(2000)
     solve_cube
  end
and indexing for routines:
  feature test_view_target is
          indexing
              attribute: create {TEST_ATTRIBUTE}.make end
          local
and has little bug when colon in rescue section:
  feature x is
          do
          ensure
          rescue
              s := ":"
              retry
          end
So, I recommend to use my slightly modified version. It also sets eif-indent-increment to 4 (default is 3) as in VS tab is 4 spaces long and value 3 formats multi-line functions calls wrong:
function_call(value1,
              value2)
And it also sets eif-body-comment-indent to 1 (default is 0) for comments.

Copy eiffel.el to emacs\lisp directory.

4.3. Batch formatting

You can run Emacs from command line and it will load your file, format and save back.

I created automaticindent.el file that you should also copy to emacs\lisp directory. It sets eiffel mode for formatting, disables creation of backups and implements indent-whole-buffer function (I found its code on Internet, perhaps it's not very efficient, but fast enough for me).

Now, you can batch format any Eiffel file (format_file.cmd):
D:\emacs\bin\emacs.exe -batch file_name.e -l automaticindent.el -f indent-whole-buffer

Note: Emacs requires that every file should contain end-of-line at the end. In batch mode it will ask you to press y to correct file with wrong format.

You can easily batch format whole project (format_dir.cmd):
for %%I in (E:\programming\cube\*.e) do format_file.cmd %%~I
And I highly recommend to do so, as it will detect and fix all files without end-of-line at the end.

4.4. Integration with Visual Studio

When we write new code in VS IDE and want to format it, we can call format_file.cmd for it.

In VS go to Tools - Macros - Macros IDE and enter this code inside any module (e.g. Module1):
Sub FormatDocument()
    If ActiveDocument().Language = "Eiffel" Then
       Dim cmdline As String = Chr(34) + "D:\emacs\format_file.cmd " + ActiveDocument().FullName() + Chr(34)
       ActiveDocument().Save()
       System.Diagnostics.Process.Start("D:\emacs\run_hidden.exe", cmdline)
    Else
       Dim objSel As TextSelection = DTE.ActiveDocument.Selection
       Dim iRow As Long = objSel.AnchorPoint.Line
       objSel.SelectAll()
       objSel.SmartFormat()
       objSel.GotoLine(iRow)
       ActiveDocument().Save()
    End If
End Sub
This function consists of two parts: one for Eiffel projects and one for projects in other languages that have build in formatting support (C++, C#). So I can bind it (Tools - Customize - Keyboard) to one language-independent key.

If I call format_file.cmd directly I get annoying console window splash. So, I wrote tiny run_hidden app in C++ that can run other apps creating process with CREATE_NO_WINDOW flag, that prevents console window to appear.

Set on Tools - Options - Environment - Documents - Auto-load changes checkbox. Bind Macros.MacroProject1.Module1.FormatDocument command to your favorite key (F8) and enjoy.


Copyright (C) 2003 Sergey Vlasov