using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.NRefactory.PrettyPrinter;
namespace CodeDomAssistant
{
public partial class FormCodeAssistant : Form
{
string outputfilename = string.Empty;
List<string> savefilters = new List<string>();
FormCodeDomProviderAssemblies providerAssemblies = null;
ScintillaNet.FindReplaceDialog findReplaceDialog = null;
public FormCodeAssistant()
{
InitializeComponent();
scintillaInput.ConfigurationManager.Language = "cs";
scintillaInput.FileDrop += new EventHandler<ScintillaNet.FileDropEventArgs>(scintillaCode_FileDrop);
LoadLists();
}
void LoadLists()
{
savefilters.Clear();
cbOutput.Items.Clear();
cbCodeDom.Items.Clear();
savefilters.Add("CS|*.cs");
cbOutput.Items.Add(new OutputClass("C#", new ToCSharpConvertVisitor(), new CSharpOutputVisitor(), 0));
savefilters.Add("VB|*.vb");
cbOutput.Items.Add(new OutputClass("VB", new ToVBNetConvertVisitor(), new VBNetOutputVisitor(), 1));
LoadCodeDomAssemblies();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly ass in assemblies)
{
Type[] types = ass.GetExportedTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(System.CodeDom.Compiler.CodeDomProvider)))
{
System.CodeDom.Compiler.CodeDomProvider provider = (System.CodeDom.Compiler.CodeDomProvider)ass.CreateInstance(type.FullName);
// setup save filter for provider
string ext = provider.FileExtension;
string filter = ext.ToUpper() + "|*." + ext.ToLower();
int filterindex = -1;
for (int i = 0; i < savefilters.Count; i++)
{
if (savefilters[i] == filter)
{
filterindex = i;
break;
}
}
if (filterindex == -1)
{
filterindex = savefilters.Count;
savefilters.Add(filter);
}
OutputClass outputclass = new OutputClass(type.Name, provider, filterindex);
if (type == typeof(CodeDomCodeProvider))
{
// Can Test CodeDom Generate from our CodeDomCodeProvider
outputclass.CanTestCodeDom = true;
}
else
{
// Otherwise We Test With CodeDom Provider
cbCodeDom.Items.Add(outputclass);
}
cbOutput.Items.Add(outputclass);
}
}
}
cbOutput.SelectedIndex = 0;
cbCodeDom.SelectedIndex = 0;
}
/// <summary>
/// Get list of extra assemblies to load more
/// CodeDom Providers
/// </summary>
void LoadCodeDomAssemblies()
{
DataSet assemblyCache = DynProvider.GetAssemblyInfo();
foreach (DataRow assemblyInfo in assemblyCache.Tables[0].Rows)
{
bool load = (bool)assemblyInfo["Load"];
bool hasprovider = (bool)assemblyInfo["HasProvider"];
if (hasprovider && load)
{
string path = (string)assemblyInfo["Path"];
// we only need filename when in GAC
bool gac = (bool)assemblyInfo["IsGAC"];
if (gac)
{
Assembly.LoadWithPartialName(Path.GetFileNameWithoutExtension(path));
}
else
{
Assembly.LoadFile(path);
}
}
}
}
void scintillaCode_FileDrop(object sender, ScintillaNet.FileDropEventArgs e)
{
try
{
this.Cursor = Cursors.WaitCursor;
if (e.FileNames.Length > 0)
{
OpenInputFile(e.FileNames[0]);
}
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
finally
{
this.Cursor = Cursors.Default;
}
}
private void buttonGenerate_Click(object sender, EventArgs e)
{
this.tabControl1.SelectedTab = this.tabOutputCode;
ICSharpCode.NRefactory.SupportedLanguage language = ICSharpCode.NRefactory.SupportedLanguage.CSharp;
if (this.radioVB.Checked)
{
language = ICSharpCode.NRefactory.SupportedLanguage.VBNet;
}
TextReader rd = new StringReader(this.scintillaInput.Text);
try
{
OutputClass outputclass = (OutputClass)cbOutput.SelectedItem;
Generate(language, rd, outputclass);
// allow testing of codedom code
buttonTestCodeDom.Enabled = outputclass.CanTestCodeDom;
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
finally
{
rd.Close();
}
}
void Generate(ICSharpCode.NRefactory.SupportedLanguage language, TextReader inputstream, OutputClass output)
{
ICSharpCode.NRefactory.IParser parser = ParserFactory.CreateParser(language, inputstream);
parser.Parse();
if (parser.Errors.Count > 0)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(null, "Error Parsing Input Code");
dlg.ShowDialog();
return;
}
if (output.CodeDomProvider != null)
{
CodeDomVisitor visit = new CodeDomVisitor();
visit.VisitCompilationUnit(parser.CompilationUnit, null);
// Remove Unsed Namespaces
for (int i = visit.codeCompileUnit.Namespaces.Count - 1; i >= 0; i--)
{
if (visit.codeCompileUnit.Namespaces[i].Types.Count == 0)
{
visit.codeCompileUnit.Namespaces.RemoveAt(i);
}
}
CodeGeneratorOptions codegenopt = new CodeGeneratorOptions();
codegenopt.BlankLinesBetweenMembers = true;
System.IO.StringWriter sw = new System.IO.StringWriter();
output.CodeDomProvider.GenerateCodeFromCompileUnit(visit.codeCompileUnit, sw, codegenopt);
this.scintillaOutput.Text = sw.ToString();
sw.Close();
}
else
{
AbstractAstTransformer transformer = output.CreateTransformer();
// do what SharpDevelop does...
List<ISpecial> specials = parser.Lexer.SpecialTracker.CurrentSpecials;
if (language == SupportedLanguage.CSharp && transformer is ToVBNetConvertVisitor)
{
PreprocessingDirective.CSharpToVB(specials);
}
else if (language == SupportedLanguage.VBNet && transformer is ToCSharpConvertVisitor)
{
PreprocessingDirective.VBToCSharp(specials);
}
parser.CompilationUnit.AcceptVisitor(transformer, null);
IOutputAstVisitor prettyprinter = output.CreatePrettyPrinter();
using (SpecialNodesInserter.Install(specials, prettyprinter))
{
prettyprinter.VisitCompilationUnit(parser.CompilationUnit, null);
}
this.scintillaOutput.Text = prettyprinter.Text;
}
}
private void radioVB_CheckedChanged(object sender, EventArgs e)
{
scintillaInput.ConfigurationManager.Language = "vb";
}
private void radioCSharp_CheckedChanged(object sender, EventArgs e)
{
scintillaInput.ConfigurationManager.Language = "cs";
}
void OpenInputFile(string filename)
{
string text = string.Empty;
if (File.Exists(filename))
{
StreamReader reader = File.OpenText(filename);
text = reader.ReadToEnd();
reader.Close();
}
scintillaInput.Text = text;
}
/// <summary>
/// Save Output File
/// </summary>
void SaveOutputFile(string filename)
{
if (filename.Length != 0)
{
// Save File
StreamWriter writer = new StreamWriter(filename);
writer.Write(this.scintillaOutput.Text);
writer.Flush();
writer.Close();
outputfilename = filename;
}
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
this.Cursor = Cursors.WaitCursor;
System.Windows.Forms.OpenFileDialog openfile = new System.Windows.Forms.OpenFileDialog();
openfile.Filter = "C#|*.cs|VB|*.vb|All Files|*.*";
openfile.FilterIndex = 0;
openfile.Title = "Open Source File";
if (openfile.ShowDialog() == DialogResult.OK)
{
OpenInputFile(openfile.FileName);
}
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
finally
{
this.Cursor = Cursors.Default;
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void fileToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void saveOutputStripMenuItem_Click(object sender, EventArgs e)
{
try
{
this.Cursor = Cursors.WaitCursor;
// Available Output Save File Extensions
string filter = string.Empty;
foreach (string f in savefilters)
{
if (filter.Length > 0)
{
filter += "|";
}
filter += f;
}
if (filter.Length > 0)
{
filter += "|";
}
filter += "All Files|*.*";
System.Windows.Forms.SaveFileDialog savefile = new System.Windows.Forms.SaveFileDialog();
savefile.Filter = filter;
savefile.FilterIndex = ((OutputClass)cbOutput.SelectedItem).SaveFilterIndex + 1;
savefile.Title = "Save Output File";
savefile.AddExtension = true;
savefile.OverwritePrompt = true;
savefile.ValidateNames = true;
if (savefile.ShowDialog() == DialogResult.OK)
{
SaveOutputFile(savefile.FileName);
}
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
finally
{
this.Cursor = Cursors.Default;
}
}
private void buttonTestCodeDom_Click(object sender, EventArgs e)
{
try
{
this.Cursor = Cursors.WaitCursor;
this.tabControl1.SelectedTab = this.tabTestCodeDom;
CompileTestCodeDom(this.scintillaOutput.Text);
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
finally
{
this.Cursor = Cursors.Default;
}
}
/// <summary>
/// Compile CodeDom Code
/// </summary>
void CompileTestCodeDom(string code)
{
try
{
OutputClass outputclass = (OutputClass)cbCodeDom.SelectedItem;
CodeDomProvider provider = outputclass.CodeDomProvider;
string codesnippet =
@"
public string GenerateCode()
{
" + code + @"
CodeGeneratorOptions codegenopt = new CodeGeneratorOptions();
codegenopt.BlankLinesBetweenMembers = true;
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
" + provider.GetType().Name + @" provider = new " + provider.GetType().Name + @"();
provider.GenerateCodeFromCompileUnit(_compileunit1, sw, codegenopt);
return sw.ToString();
}
}
";
CodeDomAssistant.CSharpSnippet snippet = new CSharpSnippet(codesnippet);
snippet.Namespaces.Add("System.CodeDom");
snippet.Namespaces.Add("System.CodeDom.Compiler");
snippet.Namespaces.Add(provider.GetType().Namespace);
// add referenced assemblies
Assembly ass = provider.GetType().Assembly;
if (!ass.GlobalAssemblyCache)
{
snippet.ReferencedAssemblies.Add(ass.Location);
}
object[] invokeParams = new object[] {};
object outputcode = snippet.Execute("GenerateCode", invokeParams);
if (outputcode != null)
{
this.scintillaTestCodeDom.Text = outputcode.ToString();
}
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
}
private void codeDomProvidersToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
if (providerAssemblies == null)
{
providerAssemblies = new FormCodeDomProviderAssemblies();
providerAssemblies.FormClosed += new FormClosedEventHandler(providerAssemblies_FormClosed);
providerAssemblies.Show();
providerAssemblies.LoadAssemblies(false);
}
else
{
providerAssemblies.Activate();
}
}
catch (Exception ex)
{
ICSharpCode.Core.ExceptionDialog dlg = new ICSharpCode.Core.ExceptionDialog(ex, "Error Generating CodeDom");
dlg.ShowDialog();
}
}
void providerAssemblies_FormClosed(object sender, FormClosedEventArgs e)
{
if (providerAssemblies != null &&
providerAssemblies.DialogResult == DialogResult.OK)
{
LoadLists();
}
providerAssemblies = null;
}
private void findToolStripMenuItem_Click(object sender, EventArgs e)
{
if (findReplaceDialog == null)
{
findReplaceDialog = new ScintillaNet.FindReplaceDialog();
findReplaceDialog.FormClosing += new FormClosingEventHandler(findReplaceDialog_FormClosing);
}
InitFindReplace();
}
void findReplaceDialog_FormClosing(object sender, FormClosingEventArgs e)
{
findReplaceDialog = null;
}
void InitFindReplace()
{
if (findReplaceDialog == null)
return;
if (this.tabControl1.SelectedTab == this.tabTestCodeDom)
{
findReplaceDialog.Scintilla = this.scintillaTestCodeDom;
}
else if (this.tabControl1.SelectedTab == this.tabOutputCode)
{
findReplaceDialog.Scintilla = this.scintillaOutput;
}
else
{
findReplaceDialog.Scintilla = this.scintillaInput;
}
findReplaceDialog.Show();
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
InitFindReplace();
}
}
}