001/* 002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon) 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 */ 009 010package org.eclipse.golo.doc; 011 012import org.eclipse.golo.compiler.parser.*; 013import org.eclipse.golo.compiler.ir.*; 014import org.eclipse.golo.compiler.GoloCompiler; 015 016import java.util.*; 017 018public class ModuleDocumentation implements DocumentationElement { 019 020 private String moduleName; 021 private int moduleDefLine; 022 private String moduleDocumentation; 023 024 private final Map<String, Integer> imports = new TreeMap<>(); 025 private final Map<String, Integer> moduleStates = new TreeMap<>(); 026 private final SortedSet<FunctionDocumentation> functions = new TreeSet<>(); 027 private final Map<String, AugmentationDocumentation> augmentations = new TreeMap<>(); 028 private final SortedSet<StructDocumentation> structs = new TreeSet<>(); 029 private final SortedSet<UnionDocumentation> unions = new TreeSet<>(); 030 private final Set<NamedAugmentationDocumentation> namedAugmentations = new TreeSet<>(); 031 032 /** 033 * {@inheritDoc} 034 */ 035 @Override 036 public String type() { 037 return "module"; 038 } 039 040 ModuleDocumentation(GoloModule module) { 041 module.accept(new ModuleVisitor()); 042 } 043 044 public static ModuleDocumentation load(String filename, GoloCompiler compiler) throws java.io.IOException { 045 return new ModuleDocumentation(compiler.transform(compiler.parse(filename))); 046 } 047 048 public String goloVersion() { 049 return org.eclipse.golo.cli.command.Metadata.VERSION; 050 } 051 052 public SortedSet<StructDocumentation> structs() { 053 return structs; 054 } 055 056 public SortedSet<UnionDocumentation> unions() { 057 return unions; 058 } 059 060 public SortedSet<FunctionDocumentation> functions() { 061 return functions(false); 062 } 063 064 public SortedSet<FunctionDocumentation> functions(boolean withLocal) { 065 if (withLocal) { 066 return functions; 067 } 068 TreeSet<FunctionDocumentation> pubFunctions = new TreeSet<>(); 069 for (FunctionDocumentation f : functions) { 070 if (!f.local()) { 071 pubFunctions.add(f); 072 } 073 } 074 return pubFunctions; 075 } 076 077 public String moduleName() { 078 return moduleName; 079 } 080 081 /** 082 * {@inheritDoc} 083 */ 084 @Override 085 public String name() { 086 return moduleName; 087 } 088 089 /** 090 * {@inheritDoc} 091 */ 092 @Override 093 public String fullName() { 094 return moduleName; 095 } 096 097 /** 098 * {@inheritDoc} 099 */ 100 @Override 101 public String id() { 102 return ""; 103 } 104 105 /** 106 * {@inheritDoc} 107 */ 108 @Override 109 public DocumentationElement parent() { 110 return this; 111 } 112 113 public int moduleDefLine() { 114 return moduleDefLine; 115 } 116 117 /** 118 * {@inheritDoc} 119 */ 120 @Override 121 public int line() { 122 return moduleDefLine; 123 } 124 125 public String moduleDocumentation() { 126 return (moduleDocumentation != null) ? moduleDocumentation : "\n"; 127 } 128 129 /** 130 * {@inheritDoc} 131 */ 132 @Override 133 public String documentation() { 134 return moduleDocumentation(); 135 } 136 137 public Map<String, Integer> moduleStates() { 138 return moduleStates; 139 } 140 141 public Collection<AugmentationDocumentation> augmentations() { 142 return augmentations.values(); 143 } 144 145 public Collection<NamedAugmentationDocumentation> namedAugmentations() { 146 return namedAugmentations; 147 } 148 149 public Map<String, Integer> imports() { 150 return imports; 151 } 152 153 private class ModuleVisitor implements GoloIrVisitor { 154 155 private Deque<Set<FunctionDocumentation>> functionContext = new LinkedList<>(); 156 private FunctionDocumentation currentFunction = null; 157 private UnionDocumentation currentUnion; 158 private MemberHolder currentMemberHolder; 159 private Deque<DocumentationElement> parents = new LinkedList<>(); 160 161 @Override 162 public void visitModule(GoloModule module) { 163 functionContext.push(functions); 164 parents.push(ModuleDocumentation.this); 165 moduleName = module.getPackageAndClass().toString(); 166 moduleDefLine = module.getPositionInSourceCode().getLine(); 167 moduleDocumentation = module.getDocumentation(); 168 module.walk(this); 169 } 170 171 @Override 172 public void visitModuleImport(ModuleImport moduleImport) { 173 if (!moduleImport.isImplicit()) { 174 imports.put(moduleImport.getPackageAndClass().toString(), moduleImport.getPositionInSourceCode().getLine()); 175 } 176 } 177 178 @Override 179 public void visitStruct(Struct struct) { 180 StructDocumentation doc = new StructDocumentation() 181 .parent(parents.peek()) 182 .name(struct.getName()) 183 .documentation(struct.getDocumentation()) 184 .line(struct.getPositionInSourceCode().getLine()); 185 structs.add(doc); 186 currentMemberHolder = doc; 187 parents.push(doc); 188 struct.walk(this); 189 parents.pop(); 190 currentMemberHolder = null; 191 } 192 193 @Override 194 public void visitUnion(Union union) { 195 this.currentUnion = new UnionDocumentation() 196 .parent(parents.peek()) 197 .name(union.getName()) 198 .documentation(union.getDocumentation()) 199 .line(union.getPositionInSourceCode().getLine()); 200 unions.add(this.currentUnion); 201 parents.push(currentUnion); 202 union.walk(this); 203 parents.pop(); 204 } 205 206 @Override 207 public void visitUnionValue(UnionValue value) { 208 UnionDocumentation.UnionValueDocumentation doc = this.currentUnion.addValue(value.getName()) 209 .parent(parents.peek()) 210 .documentation(value.getDocumentation()) 211 .line(value.getPositionInSourceCode().getLine()); 212 currentMemberHolder = doc; 213 parents.push(doc); 214 value.walk(this); 215 parents.pop(); 216 currentMemberHolder = null; 217 } 218 219 @Override 220 public void visitAugmentation(Augmentation augment) { 221 /* NOTE: 222 * if multiple augmentations are defined for the same target 223 * only the line of the first one is kept. 224 */ 225 String target = augment.getTarget().toString(); 226 if (!augmentations.containsKey(target)) { 227 augmentations.put(target, new AugmentationDocumentation() 228 .target(target) 229 .parent(parents.peek()) 230 .augmentationNames(augment.getNames()) 231 .line(augment.getPositionInSourceCode().getLine()) 232 ); 233 } 234 AugmentationDocumentation ad = augmentations.get(target); 235 ad.documentation(ad.documentation() + '\n' + augment.getDocumentation()); 236 functionContext.push(ad); 237 parents.push(ad); 238 augment.walk(this); 239 functionContext.pop(); 240 parents.pop(); 241 } 242 243 @Override 244 public void visitNamedAugmentation(NamedAugmentation augment) { 245 NamedAugmentationDocumentation augmentDoc = new NamedAugmentationDocumentation() 246 .parent(parents.peek()) 247 .name(augment.getName()) 248 .documentation(augment.getDocumentation()) 249 .line(augment.getPositionInSourceCode().getLine()); 250 namedAugmentations.add(augmentDoc); 251 functionContext.push(augmentDoc); 252 parents.push(augmentDoc); 253 augment.walk(this); 254 functionContext.pop(); 255 parents.pop(); 256 } 257 258 @Override 259 public void visitFunction(GoloFunction function) { 260 if (!GoloModule.MODULE_INITIALIZER_FUNCTION.equals(function.getName())) { 261 functionContext.peek().add(new FunctionDocumentation() 262 .parent(parents.peek()) 263 .name(function.getName()) 264 .documentation(function.getDocumentation()) 265 .augmentation(function.isInAugment()) 266 .line(function.getPositionInSourceCode().getLine()) 267 .local(function.isLocal()) 268 .arguments(function.getParameterNames()) 269 .varargs(function.isVarargs())); 270 } 271 } 272 273 @Override 274 public void visitLocalReference(LocalReference localRef) { 275 if (localRef.isModuleState()) { 276 moduleStates.put(localRef.getName(), localRef.getPositionInSourceCode().getLine()); 277 } 278 } 279 280 @Override 281 public void visitMember(Member member) { 282 currentMemberHolder.addMember(member.getName()) 283 .parent(parents.peek()) 284 .documentation(member.getDocumentation()) 285 .line(member.getPositionInSourceCode().getLine()); 286 } 287 288 @Override 289 public void visitDecorator(Decorator decorator) { 290 } 291 292 @Override 293 public void visitBlock(Block block) { 294 } 295 296 @Override 297 public void visitConstantStatement(ConstantStatement constantStatement) { 298 } 299 300 @Override 301 public void visitReturnStatement(ReturnStatement returnStatement) { 302 } 303 304 @Override 305 public void visitFunctionInvocation(FunctionInvocation functionInvocation) { 306 } 307 308 @Override 309 public void visitMethodInvocation(MethodInvocation methodInvocation) { 310 } 311 312 @Override 313 public void visitAssignmentStatement(AssignmentStatement assignmentStatement) { 314 } 315 316 @Override 317 public void visitDestructuringAssignment(DestructuringAssignment assignment) { 318 } 319 320 @Override 321 public void visitReferenceLookup(ReferenceLookup referenceLookup) { 322 } 323 324 @Override 325 public void visitConditionalBranching(ConditionalBranching conditionalBranching) { 326 } 327 328 @Override 329 public void visitBinaryOperation(BinaryOperation binaryOperation) { 330 } 331 332 @Override 333 public void visitUnaryOperation(UnaryOperation unaryOperation) { 334 } 335 336 @Override 337 public void visitLoopStatement(LoopStatement loopStatement) { 338 } 339 340 @Override 341 public void visitForEachLoopStatement(ForEachLoopStatement foreachStatement) { 342 } 343 344 @Override 345 public void visitCaseStatement(CaseStatement caseStatement) { 346 } 347 348 @Override 349 public void visitMatchExpression(MatchExpression matchExpression) { 350 } 351 352 @Override 353 public void visitWhenClause(WhenClause<?> whenClause) { 354 } 355 356 @Override 357 public void visitThrowStatement(ThrowStatement throwStatement) { 358 } 359 360 @Override 361 public void visitTryCatchFinally(TryCatchFinally tryCatchFinally) { 362 } 363 364 @Override 365 public void visitClosureReference(ClosureReference closureReference) { 366 } 367 368 @Override 369 public void visitLoopBreakFlowStatement(LoopBreakFlowStatement loopBreakFlowStatement) { 370 } 371 372 @Override 373 public void visitCollectionLiteral(CollectionLiteral collectionLiteral) { 374 } 375 376 @Override 377 public void visitCollectionComprehension(CollectionComprehension collectionComprehension) { 378 } 379 380 @Override 381 public void visitNamedArgument(NamedArgument namedArgument) { 382 } 383 } 384 385}