How to count number of methods per java class using c sharp? - c#

I have to complete a project in C# to find number of methods per java class.
I could find all methods in the .java file using c# regular expression, but what I want is to find the number of methods per each and every class, including inner classes. Can any one help me.
string[] lines = File.ReadAllLines(file);
int countLine = 0;
int AllCount = 0;
foreach (string line in lines)
{
countLine = MethodsCount(line);
AllCount = AllCount + countLine;
}
label5.Text = AllCount.ToString();
Here's the method-counting method.
private int MethodsCount (string LineOperator)
{
int count = 0;
string[] words = LineOperator.Split('{');
foreach (string word in words)
{
if (Regex.IsMatch(word, #"(static\s|final\s)?(public|private|internal)(\sstatic|\sfinal)?\s(int|boolean|void|double|String|long|String\[\]|String\[\]\[\])?\s([a-z]|[A-Z]+[a-z]+|[a-z]+[A-Z]+)+(\s)*\((\s|\n|\r)*"))
{
count = count + 1;
}
}
return count;
}
if we consider a class
public class vehicle {
public method1() {
---------
}
public method2() {
------
}
public class car extends vehicle {
public method3() {
-------
}
}
}
I want to get the output there are this number of methods in vehicle class,this number of methods in car class like wise.

Parsing a Java source file with just regex is flaky at best. There are so many different ways to format or annotate the code that you'll easily miss valid method declarations. The regex in your code sample does not handle line breaks, generic methods, the throws clause, arbitrary return types, the synchronized modifier or annotated arguments, two method declarations on the same line...
You'd have to drop regex and build (or reuse) a full parser to be sure you get everything. Fortunately, if you have access to a JDK you can take a shortcut.
First, compile the Java source code. This will give you an output directory full of .class files (inner classes get their own file). Scan the output directory to collect all the class names you need to analyze.
Then, for each class, run the javap command, which will give you this kind of output:
barend#TURMINDER-XUSS /tmp$ javap java.util.Iterator
Compiled from "Iterator.java"
public interface java.util.Iterator{
public abstract boolean hasNext();
public abstract java.lang.Object next();
public abstract void remove();
}
This is much easier to parse than a full Java source file. You can just count all lines containing \s[a-zA-Z][a-zA-Z0-9_]*\( and you have your method count. Use the 'compiled from' information to get to the method count per source file.
(edit) NOTE: javap doesn't print private methods by default. pass the -private argument to include these in the output.

Related

Set a variable within a Unity class

I'm currently following a brackeys tutorial on dialogue, however I want to import multiple names, as well as multiple lines of dialogue along with them, through a text file rather than handwriting them. This differs greatly from the tutorial, so I'm stuck on creating a Dialogue class. Here's what I wrote up:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Dialogue {
// text file input
public TextAsset textFile;
// list containing each line of the text file
protected string[] textLines;
// lists containing names and dialogues (written in the file like so: Bob;I like pancakes)
protected string[] names;
protected string[] dialogues;
// splits up the text file into the list of lines
textLines = textFile.text.Split('\n');
// iterates over the course of the list of lines, splitting up the names and dialogue, then sorting each into its respective list
for (int i = 0; i <= textLines.Length - 1; i++) {
names.Add(textLines[i].Split(';')[0]);
dialogue.Add(textLines[i].Split(';')[1]);
}
}
Unity, however, does not like this, and spits out loads of errors such as:
Assets\scripts\Dialogue.cs(12,15): error CS1519: Invalid token '=' in class, struct, or interface member declaration
and
Assets\scripts\Dialogue.cs(12,36): error CS1519: Invalid token '(' in class, struct, or interface member declaration
among others.
I assume there are limits when working with unity classes such as this one, however I evidently don't know them, and after looking through the internet, I was unable to find them. Any help with this is appreciated!
NOTE: I have never used Unity before, so take this with a grain of salt.
You can only assign class fields when you declare them, and you can only place for loops inside functions and properties (get and set are technically functions). Though class fields ARE modified in the application's lifetime, so there is no need to worry.
Also, string[]s do not have the .Add() method in them. Either convert the array into a List<string>, do an expensive operation that pushes new elements into an array or define a fixed size for the array.
You can do this:
/**
* You can do one of these:
* protected List<string> names; (we will use this)
* protected string[] names = new string[SOME_SIZE];
* protected string[] names; (and push elements)
*/
void AssignTextLines() {
// splits up the text file into the list of lines
textLines = textFile.text.Split('\n');
// iterates over the course of the list of lines, splitting up the names and dialogue, then sorting each into its respective list
for (int i = 0; i < textLines.Length; /* you don't need -1! */ i++) {
names.Add(textLines[i].Split(';')[0]); // only for List<T>!!
dialogues.Add(textLines[i].Split(';')[1]);
}
}
or this:
protected string[] textLines = textFile.text.Split('\n');
void Something() {
// then do the thing above
for (int i = 0; i < textLines.Length; i++) {
names.Add(textLines[i].Split(';')[0]); // only for List<T>!!
dialogues.Add(textLines[i].Split(';')[1]);
}
}
You can also replace the for loop with a foreach loop.
foreach (string txt in textLines) {
names.Add(txt.Split(';')[0]); // only for List<T>!!
dialogues.Add(txt.Split(';')[1]);
}
The error in your code is that you have written these:
// splits up the text file into the list of lines
textLines = textFile.text.Split('\n');
// iterates over the course of the list of lines, splitting up the names and dialogue, then sorting each into its respective list
for (int i = 0; i <= textLines.Length - 1; i++) {
names.Add(textLines[i].Split(';')[0]);
dialogue.Add(textLines[i].Split(';')[1]);
}
Inside the class instead of a method inside the class.
Coming to the actual problem, I think you should use a ScriptableObject in this case. They provide an Awake (Similar to Awake in MonoBehavior) method in which you can write the above code so that it gets executed when the game starts.
[CreateAssetMenu(fileName="Dialogue Asset", menuName="My Game/Dialogue Asset")]
public class Dialogue: ScriptableObject {
// text file input
public TextAsset textFile;
// list containing each line of the text file
protected string[] textLines;
// lists containing names and dialogues (written in the file like so: Bob;I like pancakes)
protected string[] names;
protected string[] dialogues;
void Awake() {
textLines = textFile.text.Split('\n');
for (int i = 0; i <= textLines.Length - 1; i++) {
names.Add(textLines[i].Split(';')[0]);
dialogue.Add(textLines[i].Split(';')[1]);
}
}
}
Now you can access the textLines and other things when the game is running. To create a new dialogue asset, you can go to Asset/My Game/Dialogue Asset from the menu bar in Unity and Edit them in the inspector. This is just a brief overview of ScriptableObject class. I suggest you watch Scriptable Objects - Brackey's to get the concept of scriptable objects better.

Not able to read a file into structure MQL5 MT5

I am trying to read a file into structure, but failed as there was a compilation error. See what I tried:
struct file_row_struct
{
datetime file_time;
string file_range_green;
string file_range_red;
double file_dist_green_red;
double file_slope_green;
double file_slope_red;
string file_prev_color;
string file_current_color;
}filerow[];
int size = 1;
FileReader = FileOpen(file_read_path,FILE_READ|FILE_CSV,',');
if(FileReader != INVALID_HANDLE)
{
//while(!FileIsEnding(FileReader))
// linecount++;
while(!FileIsEnding(FileReader))
{
FileReadStruct(FileReader,filerow,size);
size++;
}
Print("File Opened successfully");
//PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
FileClose(FileReader);
}
else Print("Not Successful in opening file: %s ", GetLastError());
The gist of sample file is available at: Sample data
The compilation error that I encountered is as follows:
'filerow' - structures containing objects are not allowed NeuralExpert.mq5 108 36
Kindly, suggest me what I have mistaken. My guess is that there is an availability of the string member function in the structure, hence it is not allowing.
Structures are simple types in MQL. That means you can have integer and floating values of all kinds in it (anything that casts to ulong and double) and some others. That also means you cannot have strings and other structures in it. If you have strings in the structure - you cannot pass by reference and many other problems (so it is better to say complex types are not supported in structures, you still may have them but it is your responsibility to do everything correctly).
Since you cannot pass structures by reference, you cannot use FileReadStruct().
What to do - I would suggest use of a CObject-based class and CArrayObj to hold them instead of filerow[].
class CFileRow : public CObject
{
//8 fields
public:
CFileRow(const string line)
{
//convert string line that you are to read from file into class
}
~CFileRow(){}
};
CArrayObj* fileRowArray = new CArrayObj();
while(!FileIsEnding(FileReader))
{
string line=FileReadString(FileReader);
fileRowArray.Add(new CFileRow(line));
}

Display unique number before array beginning C#

I was working on a small program that basically reads from a txt multiple arrays and writes them to another file, but, additionally, it should generate a unique number and place it just before the information. I got the first part working with no problems but the second part is causing me problems even though it should work.
public static void Main(string[] args)
{
StreamReader vehiclereader = new StreamReader(#"C:\Users\Admin\Desktop\Program\vehicles.txt");
string line = vehiclereader.ReadToEnd();
string ID;
string category;
string Type;
string Brand;
string Model;
string Year;
string Colour;
while (line != null)
{
var parts = line.Split(',');
Type = parts[0];
Brand = parts[1];
Model = parts[2];
Year = parts[3];
Colour = parts[4];
Console.WriteLine(line);
string[] lines = { line };
System.IO.File.WriteAllLines(#"C:\Users\Admin\Desktop\Program\vehicles2.txt", lines);
List<string> categories = new List<string>();
categories.Add(Type);
int count = categories.Where(x => x.Equals(Type)).Count();
ID = Type.Substring(0, 4) + count.ToString("00");
Console.ReadKey();
}
}
}
Currently, this code reads from a txt file, displays it into the console and writes it back to another txt file. This is fine, the part that is not willing to work is the unique number generator.
Last 5 lines of code are supposed to add a unique number just before 'Type' data and would always start from 001. If the 'Type' data is identical, then the number just grows in ascending order. Otherwise, the unique number should reset for new types and start counting from 001 and should keep growing for identical types. (e.g. For all lightweight vehicles the counter should be the same and for heavyweight vehicles the counter should be different but count all of the heavy vehicles)
I'm open to any help or suggestions!
There are a variety of issues and suggestions with this code, allow me to list them before providing a corrected version:
StreamReader is disposable, so put it in a "using" block.
ReadToEnd reads the entire file into a single string, whereas your code structure is expecting it to return a line at a time, so you want the "ReadLine" method.
The value of line does not get modified within your loop, so you will get an infinite loop (program that never ends).
(Suggestion) Use lower case letters at the start of your variable names, it will help you spot what things are variables and what are classes/methods.
(Suggestion) The local variables are declared in a wider scope than they are needed. There is no performance hit to only declaring them within the loop, and it makes your program easier to read.
"string[] lines = { line };" The naming implies that you think this will split the single line into an array of lines. But actually, it will just create an array with one item in it (which we've already established is the entire contents of the file).
"category" is an unused variable; but actually, you don't use Brand, Model, Year or Colour either.
It would have helped if the question had a couple of lines as an example of input and output.
Since, you're processing a line at a time, we might as well write the output file a line at a time, rather than hold the entire file in memory at once.
The ID is unused, and that code is after the line writing the output file, so there is no way it will appear in there.
"int count = categories.Where(x => x.Equals(type)).Count();" is inefficient, as it iterates through the list twice: prefer "int count = categories.Count(x => x.Equals(type));"
Removed the "Console.Write", since the output goes to a file.
Is that "Console.ReadKey" meant to be within the loop, or after it? I put it outside.
I created a class to be responsible for the counting, to demonstrate how it is possible to "separate concerns".
Clearly I don't have your files, so I don't know whether this will work.
class Program
{
public static void Main(string[] args)
{
var typeCounter = new TypeCounter();
using (StreamWriter vehicleWriter = new StreamWriter(#"C:\Users\Admin\Desktop\Program\vehicles2.txt"))
using (StreamReader vehicleReader = new StreamReader(#"C:\Users\Admin\Desktop\Program\vehicles.txt"))
{
string line;
while ((line = vehicleReader.ReadLine()) != null)
{
var parts = line.Split(',');
string type = parts[0].Substring(0, 4); // not sure why you're using substring, I'm just matching what you did
var identifier = typeCounter.GetIdentifier(type);
vehicleWriter.WriteLine($"{identifier},{line}");
}
}
Console.ReadKey();
}
}
public class TypeCounter
{
private IDictionary<string, int> _typeCount = new Dictionary<string, int>();
public string GetIdentifier(string type)
{
int number;
if (_typeCount.ContainsKey(type))
{
number = ++_typeCount[type];
}
else
{
number = 1;
_typeCount.Add(type, number);
}
return $"{type}{number:00}"; // feel free to use more zeros
}
}

Named Parameters used outside of class

I understand in C# there is such thing as named parameters so that is a bit misleading. The question I have is what they should be called in general.
In my time using libraries in other languages I've sometimes run across predefined values that can be used within functions of a class.
object.myFunc(SPECIAL_VALUE);
It's usually named in all capitol letters and is a very specific value within the function. I figure it behaves much like a public static string but when I use this idea intellisense doesn't pick this up. Can someone inform me of the general name of this kind of parameter option and if they exist, pros and cons of using such a thing.
Thanks,
Normally, those kind of constants in C# are declared and cased like this...
public const String MyConstantThingHere = "Some value";
In Java, it would be more like...
public static final String MY_CONSTANT_THING_HERE = "Some value";
I would simply call these public class constants. See HERE.
Also, for reference: http://www.dofactory.com/reference/csharp-coding-standards
You can also use static imports to refer to them...
See here: static imports in c#
I'm not really sure, what you mean. The concept of named parameters in C# is shown in this example:
namespace Testconsole {
public class obj {
public int myFunc(int value1, int value2 = 4, int value3 = 8) {
return value1 + value2 + value3;
}
}
class Program {
static void Main(string[] args) {
obj adder = new obj();
Console.WriteLine(adder.myFunc(value1: 1, value3: 1));
Console.ReadLine();
}
}
}
Testconsole returns 6: value1 is set with '1', value3 is set with '1', value2 is missing and therefore filled with default value '4'.
Also it is possible to pass a public static String into a Function:
namespace Testconsole {
public class obj {
public String myFunc(String mySpecialValue) {
return "now I " + mySpecialValue;
}
}
class Program {
public static String SPECIAL_VALUE = "got it";
static void Main(string[] args) {
obj Learn = new obj();
Console.WriteLine(Learn.myFunc(SPECIAL_VALUE));
Console.ReadLine();
}
}
}
Console output:
Now I got it.
What you are referring to is a "constant." They serve two purposes:
They ensure that a value that has some meaning (a "special value", as you said) is declared in one place and re-used so that if it changes we change it in one place.
They make our code more readable. For example, we might want two always display the top four items from a list on a web page. And we might have an input that should always be four characters in length. If other people just read our code and see the number 4 here and there it might not be apparent what that number 4 means. We want our code to be as easy to understand as possible.
So when we declare
const int NUMBER_OF_ITEMS_TO_DISPLAY = 4
or
const string MAX_INPUT_LENGTH_SETTINGS_KEY = "maximumInputLength"
Then when we use those constants in our code other people can tell what they mean.
The opposite of using constants is called using "magic numbers" or "magic strings." They just appear in our code without context or explanation. It might just be value we arbitrarily picked, but declaring it as a constant gives it context and meaning.
The capital letters aren't required. They're just a convention that makes constants easy to recognize.

Using Sprache to parse Enums from identifiers?

I am starting to use Sprache to parse a domain specific language for math expressions. I know I can parse an identifier using something like this:
static readonly Parser<string> Identifier =
from leading in Parse.WhiteSpace.Many()
from first in Parse.Letter.Once()
from rest in Parse.LetterOrDigit.Many()
from trailing in Parse.WhiteSpace.Many()
select new string(first.Concat(rest).ToArray());
From this I want to build a parser that only succeeds if the Identifier token is one of the text values of an Enum. So say I have an Enum called Dimension, with values Dimension.Location and Dimension.Time. I want to make
static readonly Parser<Dimension> DimensionIdentifier = ...
that only succeeds if what is being parsed is an Identifier and if the token string of the identifier is one of the enum names ("Location" or "Time"), and that returns the enum value, Dimension.Location or Dimension.Time respectively. Can someone help with what is probably a simple question? Thanks!
I use the following approach:
public static Parser<TEnum> ParseEnum()
{
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Select(value => Parse.IgnoreCase(Enum.GetName(typeof(TEnum), value)).Return(value))
.Aggregate((x, y) => x.Or(y));
}
It's similar to dbugger's answer, as it's still based on Parse.Or, but written in a more functional style.
Very nice solution stolen from here...
http://www.codewise-llc.com/blog/2015/8/13/parsing-enum-values-with-sprache
Build a typed helper class to build the parser for a given enum...
public static class EnumParser<T>
{
public static Parser<T> Create()
{
var names = Enum.GetNames(typeof(T));
var parser = Parse.IgnoreCase(names.First()).Token()
.Return((T)Enum.Parse(typeof(T), names.First()));
foreach (var name in names.Skip(1))
{
parser = parser.Or(Parse.IgnoreCase(name).Token().Return((T)Enum.Parse(typeof(T), name)));
}
return parser;
}
}
Then your parser is simply this...
public static Parser<Dimension> Dimension = EnumParser<Dimension>.Create();
And some unit tests (change the class name to whatever you are using, I was using the Sprache tutorial to get started)...
[Test]
[TestCase("Time", Dimension.Time)]
[TestCase("Location", Dimension.Location)]
public void ShouldGetProperEnumValue(string enumValueName, Dimension expected)
{
var eValue = QuestionnaireGrammar.Dimension.Parse(enumValueName);
Assert.AreEqual(expected, eValue);
}
[Test]
[ExpectedException]
[TestCase("Fredo")]
public void ShouldFailIfNotInList(string enumValueName)
{
var eValue = QuestionnaireGrammar.Dimension.Parse(enumValueName);
}
Interesting library, happy to learn about it.
OK, fairly easy to chain parsers...
Created a copy of your identity parser, and called it Identifier2 to keepit clear...
public static readonly Parser<string> Identifier2 =
from leading in Parse.WhiteSpace.Many()
from first in Parse.Letter.Once()
from rest in Parse.LetterOrDigit.Many()
from trailing in Parse.WhiteSpace.Many()
select new string(first.Concat(rest).ToArray());
Then added a compound parser that takes the results of the Identifier2 parser and uses the Dimension parser...
public static readonly Parser<Dimension> IdentityDimension =
from result in Identifier2
select Dimension.Parse(result);
Though not sure what you are buying -- enum parser already seems to do everything the identifier parser does.

Categories