Skip to content

Commit

Permalink
Merge pull request #3 from vladbatushkov/alpha3
Browse files Browse the repository at this point in the history
Version Alpha3
  • Loading branch information
vladbatushkov authored May 18, 2021
2 parents 03062b2 + 585a7c5 commit bd8088b
Show file tree
Hide file tree
Showing 15 changed files with 636 additions and 471 deletions.
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS sdk
FROM mcr.microsoft.com/dotnet/sdk:3.1-alpine AS sdk
WORKDIR /src
COPY Strazh/Strazh.csproj Strazh/Strazh.csproj
RUN dotnet restore /src/Strazh/Strazh.csproj
Expand All @@ -8,6 +8,8 @@ WORKDIR /src
COPY Strazh Strazh/
RUN dotnet build /src/Strazh/Strazh.csproj -c Release -o /app
WORKDIR /app
ENV cs=neo4j:neo4j:neo4j
ENV pl=Project.csproj
CMD ["sh", "-c", "dotnet Strazh.dll --credentials $cs --pathlist $pl"]
ENV c="neo4j:neo4j:neo4j"
ENV t="all"
ENV s="none"
ENV p=""
CMD ["sh", "-c", "dotnet Strazh.dll -c $c -t $t -s $s -p $p"]
37 changes: 11 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,6 @@ dotnet ./app/Strazh.dll -c neo4j:neo4j:strazh -p ./Strazh/Strazh.csproj

### docker

**Dockerfile**
```
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS sdk
WORKDIR /src
COPY Strazh/Strazh.csproj Strazh/Strazh.csproj
RUN dotnet restore /src/Strazh/Strazh.csproj
FROM sdk as build
WORKDIR /src
COPY Strazh Strazh/
RUN dotnet build /src/Strazh/Strazh.csproj -c Release -o /app
WORKDIR /app
ENV cs=neo4j:neo4j:neo4j
ENV pl=Project.csproj
CMD ["sh", "-c", "dotnet Strazh.dll --cs $cs --pl $pl"]
```

In case you want to create a local `strazh:dev` image:

```
Expand All @@ -50,19 +33,21 @@ docker build . -t strazh:dev
Example how to run created `strazh:dev` container against the `Strazh.csproj` project (strazh can explore strazh codebase O_o )

```
docker run -it --rm --network=host -v $(pwd)/Strazh:/dest -e cs=neo4j:neo4j:strazh -e pl=/dest/Strazh.csproj strazh:dev
docker run -it --rm --network=host -v $(pwd)/Strazh:/dest -e c=neo4j:neo4j:strazh -e p=/dest/Strazh.csproj strazh:dev
```

Run with cli from `Strazh` folder: `dotnet Strazh.dll -cs neo4j:neo4j:strazh -pl ../../../Strazh.csproj`
Run with cli from `Strazh` folder: `dotnet Strazh.dll -c neo4j:neo4j:strazh -p ../../../Strazh.csproj`

Run using `dotnet run` from `Strazh` folder:
```
dotnet run -cs "neo4j:neo4j:strazh" -pl "./Strazh.csproj"
dotnet run -c "neo4j:neo4j:strazh" -p "./Strazh.csproj"
```

_- docker volume used to map folder `/Strazh` to folder `/dest` inside docker._
_- environment value `cs` used to connect to Neo4j with `database:user:password` credentials._
_- environment value `pl` used to point to list of project path inside docker container._
- docker volume used to map folder `/Strazh` to folder `/dest` inside docker.
- environment value `c` used to connect to Neo4j with `database:user:password` credentials.
- environment value `m` used to point to mode of analysis used for run.
- environment value `s` used to point to solution file inside docker container.
- environment value `p` used to point to project files inside docker container.

**docker-compose.yml**

Expand All @@ -73,14 +58,14 @@ services:
strazh:
build: .
image: vladbatushkov/strazh:1.0.0-alpha.1
image: vladbatushkov/strazh:1.0.0-alpha.3
container_name: strazh
network_mode: host
volumes:
- ./Strazh:/dest
environment:
- cs=neo4j:neo4j:strazh
- pl=/dest/Strazh.csproj
- c=neo4j:neo4j:strazh
- p=/dest/Strazh.csproj
depends_on:
- neo4j
Expand Down
110 changes: 79 additions & 31 deletions Strazh/Analysis/Analyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,98 @@
using Buildalyzer.Workspaces;
using System.Collections.Generic;
using System;
using Strazh.Database;
using static Strazh.Analysis.AnalyzerConfig;
using System.IO;

namespace Strazh.Analysis
{
public static class Analyzer
{
private static string GetProjectName(string fullName)
public static async Task Analyze(AnalyzerConfig config)
{
return fullName.Split('\\').Last().Replace(".csproj", "");
}
Console.WriteLine($"Setup analyzer...");

public static async Task<Triple[]> Analyze(string path)
{
var triples = new List<Triple>();
var manager = config.IsSolutionBased
? new AnalyzerManager(config.Solution)
: new AnalyzerManager();

var manager = new AnalyzerManager();
var analyzer = manager.GetProject(path);
var workspace = new AdhocWorkspace();
var project = analyzer.AddToWorkspace(workspace);
var projectAnalyzers = config.IsSolutionBased
? manager.Projects.Values
: config.Projects.Select(x => manager.GetProject(x));

var projectBuild = analyzer.Build().FirstOrDefault();
var currentNode = new ProjectNode(GetProjectName(project.Name));
projectBuild.ProjectReferences.ToList().ForEach(x =>
Console.WriteLine($"Analyzer ready to analyze {projectAnalyzers.Count()} project/s.");

var workspace = new AdhocWorkspace();
var isDelete = config.IsDelete;
short index = 1;
foreach (var projectAnalyzer in projectAnalyzers)
{
var node = new ProjectNode(GetProjectName(x));
triples.Add(new TripleDependsOnProject(currentNode, node));
});
projectBuild.PackageReferences.ToList().ForEach(x =>
var triples = await AnalyzeProject(index, workspace, projectAnalyzer, config.Tier);
if (triples.Count > 0)
{
await DbManager.InsertData(triples, config.Credentials, isDelete);
}
index++;
isDelete = false;
}
workspace.Dispose();
}

private static async Task<IList<Triple>> AnalyzeProject(short index, AdhocWorkspace workspace, IProjectAnalyzer projectAnalyzer, Tiers mode)
{
Console.WriteLine($"Project #{index}:");
var project = projectAnalyzer.AddToWorkspace(workspace);
var root = GetRoot(project.FilePath);
var rootNode = new FolderNode(root, root);
var projectName = GetProjectName(project.Name);
Console.WriteLine($"Analyzing {projectName} project...");

var triples = new List<Triple>();
if (mode == Tiers.All || mode == Tiers.Project)
{
var version = x.Value.Values.FirstOrDefault(x => x.Contains(".")) ?? "none";
var node = new PackageNode(x.Key, x.Key, version);
triples.Add(new TripleDependsOnPackage(currentNode, node));
});

var compilation = await project.GetCompilationAsync();
var syntaxTreeRoot = compilation.SyntaxTrees;
foreach (var st in syntaxTreeRoot)
Console.WriteLine($"Analyzing Project tier...");
var projectBuild = projectAnalyzer.Build().FirstOrDefault();
var projectNode = new ProjectNode(projectName);
triples.Add(new TripleIncludedIn(projectNode, rootNode));
projectBuild.ProjectReferences.ToList().ForEach(x =>
{
var node = new ProjectNode(GetProjectName(x));
triples.Add(new TripleDependsOnProject(projectNode, node));
});
projectBuild.PackageReferences.ToList().ForEach(x =>
{
var version = x.Value.Values.FirstOrDefault(x => x.Contains(".")) ?? "none";
var node = new PackageNode(x.Key, x.Key, version);
triples.Add(new TripleDependsOnPackage(projectNode, node));
});
Console.WriteLine($"Analyzing Project tier complete.");
}

if (project.SupportsCompilation
&& (mode == Tiers.All || mode == Tiers.Code))
{
var sem = compilation.GetSemanticModel(st);
Extractor.AnalyzeTree<ClassDeclarationSyntax>(triples, st, sem);
Extractor.AnalyzeTree<InterfaceDeclarationSyntax>(triples, st, sem);
Console.WriteLine($"Analyzing Code tier...");
var compilation = await project.GetCompilationAsync();
var syntaxTreeRoot = compilation.SyntaxTrees;
foreach (var st in syntaxTreeRoot)
{
var sem = compilation.GetSemanticModel(st);
Extractor.AnalyzeTree<ClassDeclarationSyntax>(triples, st, sem, rootNode);
Extractor.AnalyzeTree<InterfaceDeclarationSyntax>(triples, st, sem, rootNode);
}
Console.WriteLine($"Analyzing Code tier complete.");
triples = triples.GroupBy(x => x.ToString()).Select(x => x.First()).ToList();
}
var result = triples.GroupBy(x => x.ToString()).Select(x => x.First()).ToArray();
Console.WriteLine($"Codebase of project \"{currentNode.Name}\" analyzed with result of {result.Length} triples.");
return result;

Console.WriteLine($"Analyzing {projectName} project complete.");
return triples;
}

private static string GetProjectName(string fullName)
=> fullName.Split(Path.DirectorySeparatorChar).Last().Replace(".csproj", "");

private static string GetRoot(string filePath)
=> filePath.Split(Path.DirectorySeparatorChar).Reverse().Skip(1).FirstOrDefault();
}
}
62 changes: 62 additions & 0 deletions Strazh/Analysis/AnalyzerConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace Strazh.Analysis
{
public class AnalyzerConfig
{
public class CredentialsConfig
{
public string Database { get; }
public string User { get; }
public string Password { get; }

public CredentialsConfig(string credentials)
{
if (!string.IsNullOrEmpty(credentials))
{
var args = credentials.Split(":");
if (args.Length == 3)
{
Database = args[0];
User = args[1];
Password = args[2];
}
}
}
}

public enum Tiers : int
{
All = 0,
Project = 1,
Code = 2
}

public CredentialsConfig Credentials { get; }
public Tiers Tier { get; }
public string Solution { get; }
public string[] Projects { get; }
public bool IsDelete { get; }

public bool IsSolutionBased => !string.IsNullOrEmpty(Solution);

public bool IsValid => (!string.IsNullOrEmpty(Solution) && Projects.Length == 0)
|| (string.IsNullOrEmpty(Solution) && Projects.Length > 0);

public AnalyzerConfig(string credentials, string tier, string delete, string solution, string[] projects)
{
solution = solution == "none" ? "" : solution;
Credentials = new CredentialsConfig(credentials);
Tier = MapTier(tier);
IsDelete = delete != "false";
Solution = solution;
Projects = projects ?? new string[] { };
}

private Tiers MapTier(string mode)
=> (mode ?? "").ToLowerInvariant() switch
{
"project" => Tiers.Project,
"code" => Tiers.Code,
_ => Tiers.All,
};
}
}
Loading

0 comments on commit bd8088b

Please sign in to comment.