In some of visual studio solution I met, there are very much more projects inside. This is a simple script to extract and simplify the dependencies and generate VBA of Visio to draw the diagram better visualization.
import re | |
import os | |
import sys | |
def vba_vso_name(text): | |
ans = text.replace(' ', '_').replace('.', '_') | |
assert re.compile(r'^\w*$').match(ans) | |
return ans | |
def generate_VBA(d_dir_dep): | |
VBA = r''' | |
Sub aaa() | |
Dim vsoPages As Visio.Pages | |
Dim vsoPage As Visio.Page | |
Dim vsoDocument As Visio.Document | |
Dim Textline As String | |
Dim vsoShape As Visio.Shape | |
''' | |
for i,x in enumerate(list(d_dir_dep.keys())): | |
vsoname = vba_vso_name(x) | |
VBA += rf''' | |
Set {vsoname} = ActivePage.DrawRectangle({2*0}, {11.3-0.3*i}, {2*0} + 4, {11.0 - 0.3*i}) | |
{vsoname}.Text = "{x}" | |
{vsoname}.CellsSRC(visSectionCharacter, 0, visCharacterSize).FormulaU = "MIN(1,Height/TEXTHEIGHT(TheText,Width))*13&""pt""" | |
''' | |
for x in d_dir_dep: | |
for y in d_dir_dep[x]: | |
xname = vba_vso_name(x) | |
yname = vba_vso_name(y) | |
VBA += rf''' | |
Set conn = ActivePage.Drop(Visio.Application.ConnectorToolDataObject, 1, 4) | |
conn.Cells("BeginX").GlueTo {xname}.Cells("PinX") | |
conn.Cells("EndX").GlueTo {yname}.Cells("PinX") | |
''' | |
VBA += r''' | |
End Sub | |
''' | |
return VBA | |
def main(): | |
sln_path = sys.argv[1] if len(sys.argv) > 1 else None | |
if not sln_path: | |
print(f'usage: main.py /path/to/*.sln') | |
exit(1) | |
with open(sln_path, 'rt') as f: | |
all_projectes = f.readlines() | |
all_projectes = [re.compile(fr'^Project.* = (.*csproj.*)$').match(x) for x in all_projectes] | |
all_projectes = [x.group(1) for x in all_projectes if x] | |
all_projectes = [x for x in all_projectes if x] | |
all_projectes = [x.split(',') for x in all_projectes] | |
all_projectes = [[y.split('"')[1] for y in x] for x in all_projectes] | |
all_projectes = [(x, os.path.join(os.path.dirname(sln_path), proj_path)) for x,proj_path,_ in all_projectes] | |
all_projectes = [(x, os.path.abspath(proj_path)) for x,proj_path in all_projectes] | |
d_path_projname = {proj_path: proj_name for proj_name,proj_path in all_projectes} | |
d_direct_dep = {} | |
for proj_name,proj_path in all_projectes: | |
d_direct_dep[proj_name] = set() | |
with open(proj_path, 'rt') as pf: | |
deps = pf.readlines() | |
deps = [line for line in deps if '<ProjectReference Include=' in line] | |
deps = [line.split('ProjectReference Include="')[1].split('"')[0] for line in deps] | |
deps = [os.path.join(os.path.dirname(proj_path), line) for line in deps] | |
deps = [os.path.abspath(line) for line in deps] | |
d_direct_dep[proj_name] = set(d_path_projname[y] for y in deps if y in d_path_projname) | |
d_all_dep = {} | |
for x in d_direct_dep: | |
d_all_dep[x] = set() | |
queue = list(d_direct_dep[x]) | |
while queue: | |
head,queue = queue[0],queue[1:] | |
d_all_dep[x].add(head) | |
for nn in d_direct_dep[head]: | |
if nn not in d_all_dep[x]: | |
queue.append(nn) | |
for x in d_direct_dep: | |
for y in list(d_direct_dep[x]): | |
if any(y in d_all_dep[z] for z in d_direct_dep[x]): | |
d_direct_dep[x].remove(y) | |
d_direct_dep = {x:d_direct_dep[x] for x in d_direct_dep if 'test' not in x.lower()} | |
d_direct_dep = {x:[y for y in d_direct_dep[x] if y in d_direct_dep.keys()] for x in d_direct_dep} | |
for x in sorted(d_direct_dep.keys()): | |
print(x, '-->', d_direct_dep[x]) | |
print(generate_VBA(d_direct_dep)) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment