/// @brief Method to compile C# source code to check errors on it. /// Actually call a C# compiler to determine errors, using references. /// @param[in] sender Object who called this on event. /// @param[in] e `EventArgs` class with a list of argument to the event call. private void CheckSource_Click(object sender, EventArgs e) { if ((codeEditorView.TextLength > 0) && IsConsistent()) { string[] refs = new string[referencesList.Items.Count]; int i = 0; errorListView.Items.Clear(); foreach (string s in referencesList.Items) { refs[i++] = s; } if (ModuleCompiler.LoadModule(codeEditorView.Text, instanceName.Text, refs, null) != null) { MessageBox.Show("Script compiled without errors.", "Plugin Editor - Check source."); } else { ModuleCompiler.EnumerateErrors(EnumErrors); } } }
/// @brief Load a plugin from XML file. /// @details Try to open the XML definition for the plugin from the file name given as /// parameter. Then extract information from the XML (class name, auxiliary references /// and source code to compile), trying to compile the C# source code (based on /// Gear.PluginSupport.PluginBase class) and returning the new class instance. If the /// compilation fails, then it opens the plugin editor to show errors and source code. /// @param[in] FileName Name and path to the XML plugin file to open /// @returns Reference to the new plugin instance (on success) or NULL (on fail). public PluginBase LoadPlugin(string FileName) { XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreComments = true; settings.IgnoreProcessingInstructions = true; settings.IgnoreWhitespace = true; XmlReader tr = XmlReader.Create(FileName, settings); bool ReadText = false; List <string> references = new List <string>(); string instanceName = ""; string code = ""; try { while (tr.Read()) { if (tr.NodeType == XmlNodeType.Text && ReadText) { code = tr.Value; ReadText = false; } switch (tr.Name.ToLower()) { case "reference": if (!tr.IsEmptyElement) //prevent empty element generates error { references.Add(tr.GetAttribute("name")); } break; case "instance": instanceName = tr.GetAttribute("class"); break; case "code": ReadText = true; break; } } //Dynamic load and compile the plugin module as a class, giving the chip // instance as a parameter. PluginBase plugin = ModuleCompiler.LoadModule( code, instanceName, references.ToArray(), Chip ); if (plugin == null) //if it fails... { // ...open plugin editor in other window PluginEditor pe = new PluginEditor(false); pe.OpenFile(FileName, true); pe.MdiParent = this.MdiParent; pe.Show(); } else //if success compiling & instantiate the new class... { //...add the reference to the plugin list of the emulator instance AttachPlugin(plugin); Properties.Settings.Default.LastPlugin = FileName; //update location of last plugin Properties.Settings.Default.Save(); } return(plugin); } catch (IOException ioe) { MessageBox.Show(this, ioe.Message, "Failed to load program binary", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return(null); } catch (XmlException xmle) { MessageBox.Show(this, xmle.Message, "Failed to load program binary", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return(null); } finally { tr.Close(); } }
/// @brief Load a plugin from file. /// @details Try to open the XML definition for the plugin from the file name given as /// parameter. Then extract information from the XML (class name, auxiliary references /// and source code to compile), trying to compile the C# source code (based on /// Gear.PluginSupport.PluginCommon class) and returning the new class instance. If the /// compilation fails, then it opens the plugin editor to show errors and source code. /// @param[in] FileName Name and path to the XML plugin file to open /// @returns Reference to the new plugin instance (on success) or NULL (on fail). /// @throws Exception // TODO Modify the method to receive a PluginData, and delete the validation public void LoadPlugin(string FileName) { object objInst = null; //create the structure to fill data from file PluginData pluginCandidate = new PluginData(); //Determine if the XML is valid, and for which DTD version if (!pluginCandidate.ValidatePluginFile(FileName)) { string allMessages = string.Empty; //case not valid file, so show the errors. foreach (string strText in pluginCandidate.ValidationErrors) { allMessages += (strText.Trim() + "\r\n"); } /// @todo Add a custom dialog to show every error message in a grid. //show messages MessageBox.Show(allMessages, "Emulator - OpenPlugin.", MessageBoxButtons.OK, MessageBoxIcon.Error); } else //...XML plugin file is valid & system version is determined { //determine time to use to build the plugin DateTime TimeOfBuild = AssemblyUtils.GetFileDateTime(FileName); for (int i = 0; i < pluginCandidate.UseExtFiles.Length; i++) { if (pluginCandidate.UseExtFiles[i] == true) { TimeOfBuild = DateTime.FromBinary(Math.Max( TimeOfBuild.ToBinary(), AssemblyUtils.GetFileDateTime(pluginCandidate.ExtFiles[i]).ToBinary())); } } //generate the full name of the assembly corresponding to the plugin candidate string candidateAssemblyFullName = pluginCandidate.PluginAssemblyFullName(TimeOfBuild).FullName; //determine the version to look for the correct method to load it switch (pluginCandidate.PluginSystemVersion) { case "0.0": if (PluginPersistence.GetDataFromXML_v0_0(FileName, ref pluginCandidate)) { //Search and replace plugin class declarations for V0.0 plugin // system compatibility. pluginCandidate.Codes[0] = PluginSystem.ReplacePropellerClassV0_0( PluginSystem.ReplaceBaseClassV0_0(pluginCandidate.Codes[0])); } break; case "1.0": PluginPersistence.GetDataFromXML_v1_0(FileName, ref pluginCandidate); objInst = this.Chip; break; default: MessageBox.Show(string.Format("Plugin system version '{0}' not recognized " + "on file \"{1}\".", pluginCandidate.PluginSystemVersion, FileName), "Emulator - Open File.", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //add information into plugin's code to generate with assembly attributes pluginCandidate.Codes[0] = PluginSystem.InsertAssemblyDetails( pluginCandidate.Codes[0], TimeOfBuild, pluginCandidate.InstanceName, pluginCandidate.Description, pluginCandidate.PluginVersion); try { //Dynamic load and compile the plugin module as a class, giving the chip // instance as a parameter, and casting to appropriate class PluginCommon plugin = ModuleCompiler.LoadModule( pluginCandidate.Codes, //string[] codeTexts pluginCandidate.ExtFiles, //string[] sourceFiles pluginCandidate.InstanceName, //string module pluginCandidate.References, //string[] references objInst, //object objInstance pluginCandidate.PluginSystemVersion); //string pluginSystemVersion, if (plugin == null) { throw new Exception("Emulator - OpenPlugin: plugin object not generated!" + " (null response from memory loading)."); } else //if success compiling & instantiate the new instance... { //...add to the corresponding plugin list of the emulator instance AttachPlugin(plugin); //update location of last plugin Properties.Settings.Default.LastPlugin = FileName; Properties.Settings.Default.Save(); } } catch (Exception) { //open plugin editor in other window PluginEditor errorPlugin = new PluginEditor(false); if (errorPlugin.OpenFile(FileName, true)) { //remember plugin successfully loaded errorPlugin.UpdateLastPluginOpened(); //show plugin editor loaded with the faultly one errorPlugin.MdiParent = this.MdiParent; //the compilation errors are displayed in the error grid ModuleCompiler.EnumerateErrors(errorPlugin.EnumErrors); //show the error list errorPlugin.ShowErrorGrid(true); errorPlugin.Show(); } } } }
/// @brief Method to compile C# source code to check errors on it. /// Actually call a C# compiler to determine errors, using references. /// @param[in] sender Object who called this on event. /// @param[in] e `EventArgs` class with a list of argument to the event call. private void CheckSource_Click(object sender, EventArgs e) { if (String.IsNullOrEmpty(codeEditorView.Text)) { MessageBox.Show("No source code to check. Please add code.", "Plugin Editor - Check source.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { string aux = null; if (DetectClassName(codeEditorView.Text, out aux)) //class name detected? { int i = 0; instanceName.Text = aux; //show the name found in the screen field errorListView.Items.Clear(); //clear error list, if any //prepare reference list string[] refs = new string[referencesList.Items.Count]; foreach (string s in referencesList.Items) { refs[i++] = s; } try { PluginBase plugin = ModuleCompiler.LoadModule(codeEditorView.Text, instanceName.Text, refs, null); if (plugin != null) { ShowErrorGrid(false); //hide the error list MessageBox.Show("Plugin compiled without errors.", "Plugin Editor - Check source.", MessageBoxButtons.OK, MessageBoxIcon.Information); plugin.Dispose(); } else { ModuleCompiler.EnumerateErrors(EnumErrors); ShowErrorGrid(true); //show the error list } } catch (Exception ex) { MessageBox.Show("Compile Error: " + ex.ToString(), "Plugin Editor - Check source.", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else //not detected class name { instanceName.Text = "Not found!"; MessageBox.Show("Cannot detect main plugin class name. " + "Please use \"class <YourPluginName> : PluginBase {...\" " + "declaration on your source code.", "Plugin Editor - Check source.", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }