LineCounterEx 1.4 (VSProjectInfoLib 3.1)

    • Release
    • Closed Source

    Es gibt 148 Antworten in diesem Thema. Der letzte Beitrag () ist von mikeb69.

      Artentus schrieb:

      und lade sie hier hoch. Ansonsten hab ich keinen Anhaltspunkt, wo der Fehler liegt.

      Ich muss das direkt hier auf meinem PC im VS-Debugger machen, damit ich ordentliche Infos über den Fehler bekomme. Nur "ArgumentOutOfRangeException" reicht leider nicht.
      Hallo,

      ich weiß ja nicht, welche Projektmappe von allen 12 z.B. das ist.

      Und es funktioniert ja mit 2 Projektmappen.

      MFG

      Alex-Digital :D
      ~ Alex-Digital :D

      if(!Internet.VBP.Get<User>("Alex-Digital").IsOnline) this.Close(); :D
      Hallo,

      es war eine Projektmappe, die mit Cosmos erstellt wurde

      MFG

      Alex-Digital :D
      Dateien
      • TestOS2.rar

        (148,17 kB, 61 mal heruntergeladen, zuletzt: )
      ~ Alex-Digital :D

      if(!Internet.VBP.Get<User>("Alex-Digital").IsOnline) this.Close(); :D
      Ich hab tatsächlich ein wenig fahrlässig programmiert. In diesem Projekt gab es keine Angabe zur Frameworkversion, da hat es geknallt. Ich müsste jetzt aber überall Sicherheitsabfragen drin haben, damit sowas nicht wieder passiert.
      Neue Version ist im ersten Post.

      Tutorial Part 1 - Die Lib im eigenen Programm verwenden

      Hier kommt nun das Tutorial dazu, wie ihr die dem Programm beiliegende VBProjectInfoLib verwenden könnt.

      Im ersten Teil geht es lediglich darum, wie ihr die Grundfunktionalität der Lib benutzen könnt, um die Eigenschaften von VB und C# Projekten auszulesen. Darum wird es nicht sehr lang sein.
      Wenn ihr die Lib eingebunden und Artentus.ProjectInfo importiert habt, habt ihr unter anderem Zugriff auf die Klassen Solution, Project und CodeFile, welche das Kernstück der Lib bilden. Sie sind auch sehr einfach in der Benutzung.

      Edit: seit die Lib in der Version 3.0 vorliegt, ist das ganze Pluginbasiert. Ihr müsst zusätzlich also noch die folgenden Schritte befolgen:
      Importiert auch den Namespace Artentus.ProjectInfo.Packages. Jetzt hab ihr Zugriff auf die Klasse PackageManager.
      Wenn ihr die Plugins in dem Standardordner "Packages" belassen habt, so genügen folgende Aufrufe einmalig zum Programmstart:

      C-Quellcode

      1. PackageManager.LoadPackages();
      2. PackageManager.ApplyPackages();

      Solltet ihr den Ordner geändert haben, so müsst ihr dies dem PackageManager so mitteilen:

      C-Quellcode

      1. Packagemanager.PackageLocation = @".\<Name des Ordners/Pfades>";


      Um eine komplette Projektmappe zu laden verwendet einfach den folgenden Code:

      VB.NET-Quellcode

      1. Dim sampleSolution = New Solution("C:\Projects\SampleSolution\SampleSolution.sln")
      Wie ihr seht also ganz einfach. Die Klasse wird sich nun automatisch um den Rest kümmern, das bedeutet es werden sowohl die Eigenschaften der Projektmappe geladen als auch alle enthaltenen Projekte und Codedateien. Dabei wir so intelligent vorgegangen, dass nicht unterstützte Datei- und Projekttypen übersprungen werden (sie werden nachher nicht in den Eigenschaften auftauchen).

      Wenn ihr keine ganze Projektmappe sondern nur ein einzelnes Projekt laden wollt, so könnt ihr auch direkt ein Project-Objekt instanzieren. Das funktioniert dann ganz genau so wie bei der Projektmappe:

      VB.NET-Quellcode

      1. Dim sampleProject = New Project("C:\Projects\SampleSolution\SampleProject\SampleProject.vbproj")
      Dabei werden auch alle enthaltenen Codedateien geladen, wobei alle ungültigen übersprungen werden. Beachtet aber, dass nur Projektdateien vom Typ .vbproj und .csproj geladen werden können, alle anderen werfen einen Fehler. Wie ihr das ändern könnt werde ich in einem anderen Teil des Tutorials erklären.

      Ihr könnt natürlich genauso auch nur einzelne Codedateien laden:

      VB.NET-Quellcode

      1. Dim sampleCodeFile = New CodeFile("C:\Projects\SampleSolution\SampleProject\SampleClass.vb")
      Es können standardmäßig nur Codedateien mit den Endungen .vb und .cs geladen werden. Auch das kann geändert werden, was ich ebenfalls später erklären werde.

      Für eine Liste, was alles ausgelesen wird, seht ihr hier noch mal das Klassendiagramm (für diesen Teil des Tutorials ist nur die linke Hälfte von Bedeutung):


      Hier gehts zum zweiten Teil des Tutorials.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Artentus“ ()

      @Artentus:
      Bei mir funktioniert's jetzt, solange normale Projektmappen drin sind.
      Mir ist aber was aufgefallen:
      Wie werden die Projekte in der Projektmappe sortiert? Denn "1", "0", "2" in dieser Reihenfolge erscheint mir etwas komsich:


      Nochwas: Der FolderBrowserDialog sollte den zuletzt geöffneten Pfad anzeigen.
      Appropos: Hast Du Dir die VistaFBD.dll angeschaut?
      "Luckily luh... luckily it wasn't poi-"
      -- Brady in Wonderland, 23. Februar 2015, 1:56
      Desktop Pinner | ApplicationSettings | OnUtils

      Niko Ortner schrieb:

      solange normale Projektmappen drin sind.

      Heißt das, dass es bei bestimmten Projektmappen immer noch nicht funktioniert?

      Niko Ortner schrieb:

      Wie werden die Projekte in der Projektmappe sortiert?

      Sie sind in der selben Reihenfolge, wie in der .sln-Datei.

      Niko Ortner schrieb:

      Hast Du Dir die VistaFBD.dll angeschaut?

      Noch nicht, ich wollte es erst mal zum laufen bringen.
      @Artentus:
      Heißt das, dass es bei bestimmten Projektmappen immer noch nicht funktioniert?

      Also... ich hab's auf meine komplette Projektsammlung losgelassen und es hat funktioniert.
      Dann hab ich es auf den Überordner losgelassen. Da gibt's noch ein C#-Projekt, Einige Ordner mit Bildern, einige andere Ordner mit Projekten, die nicht von mir sind und einen Ordner mit einem AVR-Projekt. Da befindet sich auch eine cppproj-Datei drin.
      Ich teste das mal genauer...
      Die Ordner mit Bildern funktionieren (wird halt logischerweise nichts angezeigt)
      Das AVR-Projekt funktioniert auch (wird ebenfalls nichts angezeigt)
      C#-Projekt funktioniert (wird korrekt ausgelesen)

      Bleibt nur noch der Ordner mit den anderen Projekten... Ja, bei dem hängt sich's auf.
      Mal sehen...
      So. Ich hab die beiden Übeltäter.
      Ich habe sie angehängt. Die Datei ist zu groß. Hier ein Link:
      sendmessageservice.heliohost.o…counter/Projektmappen.zip

      Noch was: Ordner könnte man per Drag&Drop ins Programm ziehen (z.B. auf die TextBox). Das wäre eine nette Funktion.
      "Luckily luh... luckily it wasn't poi-"
      -- Brady in Wonderland, 23. Februar 2015, 1:56
      Desktop Pinner | ApplicationSettings | OnUtils
      @Artentus:
      Ich glaube bei XP und niedriger musst Du das abfragen... Moment, ich hab da glaub ich was...
      Jap.
      Environment.OSVersion.Version gibt die Version des Betriebssystems zurück. Und Windows Vista war ja 6.0, Windows 7 war 6.1 und Windows 8 war 6.2. Wenn also der Major-Teil der Version >= 6 ist, dann funktioniert der Dialog. Ansonsten zeigst Du den System.Windows.Forms.FolderBrowserDialog an.

      Und danke bitte nicht mir, sondern den Internet ;)
      Das sind einfach gefühlte 10000 COM-Interfaces mit 'nem Wrapper drumrum.
      Ich hab mir nur die Mühe gemacht, das Ganze zu VB umzuschreiben und soweit auszudünnen, dass das nötigste Funktioniert. Ist also abgeschrieben.

      PS: So spät noch wach?
      "Luckily luh... luckily it wasn't poi-"
      -- Brady in Wonderland, 23. Februar 2015, 1:56
      Desktop Pinner | ApplicationSettings | OnUtils

      Tutorial Part 2 - Unterstützung für andere Projekttypen hinzufügen

      In diesem Teil des Tutorials gehts es darum, wie ihr die Lib dazu bringen könnt, auch andere Projektdateien als .vbproj und .csproj zu akzeptieren.
      Erklären werde ich dies anhand der Standardimplementation von C#.

      Wenn ihr vorhabt, einen weiteren Projekttyp zu registrieren, so müsst ihr zunächst eine entsprechende Projektdatei ausfindig machen und diese öffnen. Achtet dabei darauf, dass ihr die Datei mit "Rechtsklick -> Öffnen mit" öffnet, da ein Doppelklick warscheinlich das Projekt in VisualStudio laden wird.
      Ich habe hier zum Beispiel die Projektdatei für MathUtils gewählt:
      Spoiler anzeigen

      XML-Quellcode

      1. <?xml version="1.0" encoding="utf-8"?>
      2. <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      3. <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
      4. <PropertyGroup>
      5. <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
      6. <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
      7. <ProjectGuid>{D2470552-33AB-4A15-8EBF-B37FA041D669}</ProjectGuid>
      8. <OutputType>Library</OutputType>
      9. <AppDesignerFolder>Properties</AppDesignerFolder>
      10. <RootNamespace>Artentus</RootNamespace>
      11. <AssemblyName>MathUtils</AssemblyName>
      12. <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
      13. <FileAlignment>512</FileAlignment>
      14. <TargetFrameworkProfile />
      15. </PropertyGroup>
      16. <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
      17. <DebugSymbols>true</DebugSymbols>
      18. <DebugType>full</DebugType>
      19. <Optimize>false</Optimize>
      20. <OutputPath>bin\Debug\</OutputPath>
      21. <DefineConstants>DEBUG;TRACE</DefineConstants>
      22. <ErrorReport>prompt</ErrorReport>
      23. <WarningLevel>4</WarningLevel>
      24. <DocumentationFile>bin\Debug\MathUtils.XML</DocumentationFile>
      25. </PropertyGroup>
      26. <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
      27. <DebugType>pdbonly</DebugType>
      28. <Optimize>true</Optimize>
      29. <OutputPath>bin\Release\</OutputPath>
      30. <DefineConstants>TRACE</DefineConstants>
      31. <ErrorReport>prompt</ErrorReport>
      32. <WarningLevel>4</WarningLevel>
      33. </PropertyGroup>
      34. <ItemGroup>
      35. <Reference Include="System" />
      36. <Reference Include="System.Core" />
      37. <Reference Include="System.Drawing" />
      38. <Reference Include="System.Xml.Linq" />
      39. <Reference Include="System.Data.DataSetExtensions" />
      40. <Reference Include="System.Data" />
      41. <Reference Include="System.Xml" />
      42. </ItemGroup>
      43. <ItemGroup>
      44. <Compile Include="ArcPolygon.cs" />
      45. <Compile Include="CirclePolygon.cs" />
      46. <Compile Include="EllipsePolygon.cs" />
      47. <Compile Include="GeneralPolygon.cs" />
      48. <Compile Include="IPolygon.cs" />
      49. <Compile Include="IVector.cs" />
      50. <Compile Include="Line3D.cs" />
      51. <Compile Include="LinearEquation.cs" />
      52. <Compile Include="LinearSystem.cs" />
      53. <Compile Include="MathHelper.cs" />
      54. <Compile Include="Matrix.cs" />
      55. <Compile Include="Matrix4x4.cs" />
      56. <Compile Include="Parser.cs" />
      57. <Compile Include="Point2D.cs" />
      58. <Compile Include="Point3D.cs" />
      59. <Compile Include="Polygon.cs" />
      60. <Compile Include="PolygonEnumerator.cs" />
      61. <Compile Include="Properties\AssemblyInfo.cs" />
      62. <Compile Include="RectanglePolygon.cs" />
      63. <Compile Include="SquareMatrix.cs" />
      64. <Compile Include="TrianglePolygon.cs" />
      65. <Compile Include="Vector.cs" />
      66. <Compile Include="Vector2.cs" />
      67. <Compile Include="Vector3.cs" />
      68. <Compile Include="Vector4.cs" />
      69. <Compile Include="VectorEnumerator.cs" />
      70. </ItemGroup>
      71. <ItemGroup>
      72. <None Include="ClassDiagram1.cd" />
      73. </ItemGroup>
      74. <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
      75. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
      76. Other similar extension points exist, see Microsoft.Common.targets.
      77. <Target Name="BeforeBuild">
      78. </Target>
      79. <Target Name="AfterBuild">
      80. </Target>
      81. -->
      82. </Project>
      Wie ihr seht, handelt es sich dabei um XmlDateien.

      Leider sind diese nicht für alle Sprachen gleich aufgebaut, weswegen ihr der Lib mitteilen müsst, wo nach bestimmten Informationen gesucht werden soll.
      Dafür gibt es das Interface IProjectTypeDescriptor, welches ihr implementieren müsst. In meinem Fall sieht das so aus:

      C-Quellcode

      1. public class CSProjectTypeDescriptor : IProjectTypeDescriptor
      2. {
      3. }
      Das Interface deklariert einige Properties, die ihr implementieren müsst. Ich werde sie nun nacheinander durchgehen.

      Zuerst müsst ihr die Dateiendung und den Namen des Projekttyps angeben. Das geschieht durch diese beiden Eigenschaften:

      C-Quellcode

      1. public string FileExtension
      2. {
      3. get { return ".csproj"; }
      4. }
      5. public string TypeName
      6. {
      7. get { return "Visual C#"; }
      8. }
      Hier genügt es, einfach einen konstanten String zurückzugeben. Beachtet auch, dass die Dateiendung den Punkt beinhalten muss.
      Der Name kann beliebig gewählt werden, er hat keine Bedeutung für das Programm.

      Dann benötigt die Lib einen Ort, an dem nach den Projektressourcen gesucht werden soll. Im Fall von C# ist das der Ordner "Resources":

      C-Quellcode

      1. public string ResourceDirectoryName
      2. {
      3. get { return @".\Resources"; }
      4. }
      Der Ordner wird dabei relativ zum Projektverzeichnis gesucht.

      Die übrigen Properties geben alle das Interface IXmlPathDescriptor zurück und beschreiben einen Ort in der XmlDatei.
      Wir müssen uns also zunächst darum kümmern, dieses Interface zu implementieren. Dafür habe ich in der Lib eine einfache Standardimplementation verwendet, ihr könnt das aber so komplex gestalten, wie ihr möchtet (dafür das Interface).
      Spoiler anzeigen

      C-Quellcode

      1. public class DefaultXmlPathDescriptor : IXmlPathDescriptor
      2. {
      3. string _path;
      4. string _attribute;
      5. bool _usesAttribute;
      6. bool _pathAvailable;
      7. public string Path
      8. {
      9. get { return _path; }
      10. }
      11. public string Attribute
      12. {
      13. get { return _attribute; }
      14. }
      15. public bool UsesAttribute
      16. {
      17. get { return _usesAttribute; }
      18. }
      19. public bool PathAvailable
      20. {
      21. get { return _pathAvailable; }
      22. }
      23. internal DefaultXmlPathDescriptor(string path, string attribute, bool usesAttribute, bool pathAvailable)
      24. {
      25. _path = path;
      26. _attribute = attribute;
      27. _usesAttribute = usesAttribute;
      28. _pathAvailable = pathAvailable;
      29. }
      30. }

      Hier eine kurze Erklärung, was die einzelnen Propreties machen:
      • PathAvailable: Gibt an, ob die gewünschte Information überhaupt verfügbar ist. Wenn False, dann wird diese Eigenschaft von der Lib komplett ignoriert.
      • Path: Gibt den Pfad in der XmlDatei an, unter dem die Informationen gespeichert sind.
      • UsesAttribute: Gibt an, ob die Informationen als Xml-Attribut vorliegen.
      • Attribute: Der Name des Attributes, in dem die Informationen enthalten sind. Ist UsesAttribute False, so wird dies ignoriert.

      Mit dieser kleinen Hilfsklasse können wir nun mit der eigentlichen Arbeit beginnen.
      Als erstes müsst ihr die restlichen Properties implementieren:
      Spoiler anzeigen

      C-Quellcode

      1. public IXmlPathDescriptor AssemblyNamePath
      2. {
      3. get { }
      4. }
      5. public IXmlPathDescriptor CodeFilesPath
      6. {
      7. get { }
      8. }
      9. public IXmlPathDescriptor FrameworkVersionPath
      10. {
      11. get { }
      12. }
      13. public IXmlPathDescriptor GlobalImportsPath
      14. {
      15. get { }
      16. }
      17. public IXmlPathDescriptor ProjectTypePath
      18. {
      19. get { }
      20. }
      21. public IXmlPathDescriptor ReferencesPath
      22. {
      23. get { }
      24. }
      25. public IXmlPathDescriptor RootNamespacePath
      26. {
      27. get { }
      28. }

      Die Namen der Properties beschreiben ziemlich genau, welcher Pfad jeweils verlangt ist.

      Wir sehen uns also die erste Property an, sie heißt AssemblyNamePath, was drauf schließen lässt, dass hier der Pfad gesucht ist, unter dem der Assemblyname zu finden ist.
      Nun suchen wir in der Projektdatei von oben nach einem Knoten, der darauf passt, und finden <AssemblyName>MathUtils</AssemblyName> mit dem Pfad "/x:Project/x:PropertyGroup/x:AssemblyName".
      Beachtet das "x:" vor jedem Knotennamen. Es wird als Platzhalter für den Xml-Namespace benötigt, ohne wird es nicht funktionieren.
      Mit diesem Wissen können wir die Property implementieren:

      C-Quellcode

      1. public IXmlPathDescriptor AssemblyNamePath
      2. {
      3. get { return new DefaultXmlPathDescriptor("/x:Project/x:PropertyGroup/x:AssemblyName", null, false, true); }
      4. }
      Das zweite Argument (also der Attributname) kann hir "null" sein, da der Assemblyname nicht als Attribut vorliegt (deswegen ist das dritte Argument auch false).

      Machen wir mit der nächsten Property, CodeFilesPath, weiter. An der Namensgebung könnt ihr schon erkennen, dass hier mehrere Knoten möglich sind (nicht zwingend erforderlich!).
      Die Codedateien sind in meinem Beispiel in solchen Knoten gespeichert: <Compile Include="ArcPolygon.cs" />
      Diesmal ist also ein Attribut mit im Spiel welches wir ebenfalls angeben müssen. Beim Rest gehen wir einfach so vor, wie im vorherigen Beispiel. Die fertige Implementation sieht dann so aus:

      C-Quellcode

      1. public IXmlPathDescriptor CodeFilesPath
      2. {
      3. get { return new DefaultXmlPathDescriptor("/x:Project/x:ItemGroup/x:Compile", "Include", true, true); }
      4. }

      Bei den Restlichen Properties könnt ihr genauso vorgehen.
      Es kann auch sein, dass eine Sprache ein Feature nicht unterstützt. Bei C# wären das zum Beispiel die globalen Importe. In solch einem Fall ist das Implementieren sogar noch einfacher:

      C-Quellcode

      1. public IXmlPathDescriptor GlobalImportsPath
      2. {
      3. get { return new DefaultXmlPathDescriptor(null, null, false, false); }
      4. }
      Das letzte false sagt der Lib, dass keine Informationen zu erwarten sind, wir können also überall null übergeben.

      Die fertige Klasse sieht dann so aus:
      Spoiler anzeigen

      C-Quellcode

      1. private class CSProjectTypeDescriptor : IProjectTypeDescriptor
      2. {
      3. public string FileExtension
      4. {
      5. get { return ".csproj"; }
      6. }
      7. public string TypeName
      8. {
      9. get { return "Visual C#"; }
      10. }
      11. public IXmlPathDescriptor AssemblyNamePath
      12. {
      13. get { return new DefaultXmlPathDescriptor("/x:Project/x:PropertyGroup/x:AssemblyName", null, false, true); }
      14. }
      15. public IXmlPathDescriptor CodeFilesPath
      16. {
      17. get { return new DefaultXmlPathDescriptor("/x:Project/x:ItemGroup/x:Compile", "Include", true, true); }
      18. }
      19. public IXmlPathDescriptor FrameworkVersionPath
      20. {
      21. get { return new DefaultXmlPathDescriptor("/x:Project/x:PropertyGroup/x:TargetFrameworkVersion", null, false, true); }
      22. }
      23. public IXmlPathDescriptor GlobalImportsPath
      24. {
      25. get { return new DefaultXmlPathDescriptor(null, null, false, false); }
      26. }
      27. public IXmlPathDescriptor ProjectTypePath
      28. {
      29. get { return new DefaultXmlPathDescriptor("/x:Project/x:PropertyGroup/x:OutputType", null, false, true); }
      30. }
      31. public IXmlPathDescriptor ReferencesPath
      32. {
      33. get { return new DefaultXmlPathDescriptor("/x:Project/x:ItemGroup/x:Reference", "Include", true, true); }
      34. }
      35. public IXmlPathDescriptor RootNamespacePath
      36. {
      37. get { return new DefaultXmlPathDescriptor("/x:Project/x:PropertyGroup/x:RootNamespace", null, false, true); }
      38. }
      39. public string ResourceDirectoryName
      40. {
      41. get { return @".\Resources"; }
      42. }
      43. }


      Als letzten Schritt braucht ihr nur noch eure neue Klasse in der Lib zu registrieren, damit sie verwendet werden kann. Dies geht mit dieser einfachen Zeile:

      C-Quellcode

      1. Project.AddProjectTypeDescriptor(new CSProjectTypeDescriptor());


      Und das wars dann, nun könnt ihr mit der Lib auch euren neuen Projekttypen laden lassen.
      Möglicherweise (sogar höchst wahrscheinlich) basiert euer Projekttyp auch auf anderen Codedateien. Wie ihr Unterstützung für diese hinzufügen könnt, erklär ich euch im nächsten Teil des Tutorials.

      Hier gehts zum dritten Teil des Tutorials.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Artentus“ ()

      Wie wärs eigentlich wenn es noch mehr Statistiken gibt. z.B. wie gesamte Zeilen ohne leere Zeilen oder Zeilen mit nur einer { ausschließen etc.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

      Tutorial Part 3 - Unterstützung für andere Codedateien hinzufügen

      Im dritten Teil des Tutorials werde ich euch nun zeigen, wie ihr die Lib dazu bringen könnt, auch Codedateien mit anderen Endungen als .vb und .cs zu laden.

      Auch für dieses Vorhaben bietet die Lib ein Interface an, es heißt ICodeFileTypeDescriptor.
      Zuerst müsst ihr es wie in Part 2 implementieren (wieder am Beispiel von C#):

      C-Quellcode

      1. public class CSCodeFileTypeDescriptor : ICodeFileTypeDescriptor
      2. {
      3. }


      Dieses Interface ist nicht ganz so komplex, wie IProjectTypeDescriptor, ihr müsst lediglich drei Member implementieren.
      Zum einen wären das Languagename und FielExtension. In meinem Beispiel würden diese so aussehen:

      C-Quellcode

      1. public string LanguageName
      2. {
      3. get { return "Visual C#"; }
      4. }
      5. public string FileExtension
      6. {
      7. get { return ".cs"; }
      8. }


      Zum anderen wäre das die Funktion ParseCode. In dieser müsst ihr die Datei einlesen, also Codezeilen, Kommentarzeilen, Leerzeilen und Gesamtzeilen zählen. Erwartet wird ein Objekt vom Typ CodeDescription, welches diese vier Dinge speichern kann.
      Hier nun die Funktion für C#:
      Spoiler anzeigen

      C-Quellcode

      1. public CodeDescription ParseCode(string codeFilePath)
      2. {
      3. var fi = new FileInfo(codeFilePath);
      4. int lines = 0;
      5. int codeLines = 0;
      6. int commentLines = 0;
      7. int emptyLines = 0;
      8. using (var fs = fi.OpenRead())
      9. using (var sr = new StreamReader(fs, Encoding.UTF8))
      10. while (!sr.EndOfStream)
      11. {
      12. var line = sr.ReadLine().Trim();
      13. lines++;
      14. if (string.IsNullOrEmpty(line))
      15. emptyLines++;
      16. else if (line.StartsWith("//"))
      17. commentLines++;
      18. else if (line.StartsWith("/*"))
      19. {
      20. commentLines++;
      21. var l = sr.ReadLine().Trim();
      22. while (!(l.EndsWith("*/") || sr.EndOfStream))
      23. {
      24. commentLines++;
      25. l = sr.ReadLine().Trim();
      26. }
      27. }
      28. else
      29. codeLines++;
      30. }
      31. return new CodeDescription(codeLines, commentLines, emptyLines, lines);
      32. }

      Erklärung:
      Die Datei wird Zeilenweise eingelesen. Für jede Zeile wird zunächst der Counter für die Gesamtzeilenanzahl inkrementiert.
      Nun wird für alle Zeilen überprüft, ob sie leer, eine Kommentarzeile oder eine Codezeile ist, und der jeweilige Counter inkrementiert.
      beachtet die Behandlung von mehrzeiligen Kommentaren (Z. 21 - 30), wo die zeilen zwischen Anfang und Ende als Kommentarzeile behandelt werden müssen, ahc wenn sich nicht mit dem Kommentarsymbol beginnen.
      Am Ende wird einfach nur ein CodeDescription-Objekt erstellt, welchem die gezählten Werte übergeben werden.

      Die vollständige Klasse sieht jetzt so aus:
      Spoiler anzeigen

      C-Quellcode

      1. private class CSCodeFileTypeDescriptor : ICodeFileTypeDescriptor
      2. {
      3. public string LanguageName
      4. {
      5. get { return "Visual C#"; }
      6. }
      7. public string FileExtension
      8. {
      9. get { return ".cs"; }
      10. }
      11. public CodeDescription ParseCode(string codeFilePath)
      12. {
      13. var fi = new FileInfo(codeFilePath);
      14. int lines = 0;
      15. int codeLines = 0;
      16. int commentLines = 0;
      17. int emptyLines = 0;
      18. using (var fs = fi.OpenRead())
      19. using (var sr = new StreamReader(fs, Encoding.UTF8))
      20. while (!sr.EndOfStream)
      21. {
      22. var line = sr.ReadLine().Trim();
      23. lines++;
      24. if (string.IsNullOrEmpty(line))
      25. emptyLines++;
      26. else if (line.StartsWith("//"))
      27. commentLines++;
      28. else if (line.StartsWith("/*"))
      29. {
      30. commentLines++;
      31. var l = sr.ReadLine().Trim();
      32. while (!(l.EndsWith("*/") || sr.EndOfStream))
      33. {
      34. commentLines++;
      35. l = sr.ReadLine().Trim();
      36. }
      37. }
      38. else
      39. codeLines++;
      40. }
      41. return new CodeDescription(codeLines, commentLines, emptyLines, lines);
      42. }
      43. }

      Um diese zu verwenden müsst ihr sie ebenfalls registrieren. Dies macht ihr mit diesem Code:

      C-Quellcode

      1. CodeFile.AddCodeFileTypeDescriptor(new CSCodeFileTypeDescriptor());

      Und damit seit ihr fertig, die der neue Dateityp wird jetzt von der Lib ausgewertet.
      Beachtet, dass ihr für manche Projekttypen mehrere Dateitypen definieren solltet, wie zum Beispiel bei C++ die .cpp- und .h-Dateien.

      Hier gehts zum vierten Teil des Tutorials.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Artentus“ ()

      Soll ich die Lib auf ein Pluginsystem umschreiben? 3
      1.  
        Ja (3) 100%
      2.  
        Nein (0) 0%
      Da die Lib ja jetzt hervorragend erweiterbar ist (siehe Tutorial) ist mir die Idee gekommen, dass das doch ein guter Pluginsystem abgeben würde.
      Was haltet ihr davon, soll ich das ganze auf Plugins umschreiben? Das hätte den Vorteil, dass man Erweiterungen auch für dieses Programm erstellen könnte, und nicht wie vorher nur für eigene (ich denke mal, dass das sowieso das einzig sinnvolle wäre).

      Edit: Umfrage hinzugefügt.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Artentus“ ()

      Sehr cool. Funktioniert einwandfrei.

      Aus persönlicher Sicht würde ich ein PlugIn-System nicht brauchen. Das Programm kann soweit schon alles. Das ist aber nur meine Sicht.
      "Luckily luh... luckily it wasn't poi-"
      -- Brady in Wonderland, 23. Februar 2015, 1:56
      Desktop Pinner | ApplicationSettings | OnUtils