SquirrelJME/SquirrelJME

View on GitHub
tools/markdown-javadoc/src/main/java/cc/squirreljme/doclet/Utilities.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.doclet;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.markdownwriter.MarkdownWriter;

/**
 * Utilities for document generation.
 *
 * @since 2022/08/24
 */
public final class Utilities
{
    /**
     * Not used.
     * 
     * @since 2022/08/24
     */
    private Utilities()
    {
    }
    
    /**
     * Returns the first line of text.
     * 
     * @param __text The text to get.
     * @return The first line of text.
     * @throws NullPointerException On null arguments.
     * @since 2022/08/24
     */
    public static String firstLine(String __text)
        throws NullPointerException
    {
        if (__text == null)
            throw new NullPointerException("NARG");
        
        // Find where the string ends.
        int len = __text.length();
        char lastChar = 0xFFFD;
        for (int i = 0; i < len; i++)
        {
            char nowChar = __text.charAt(i);
            
            // Whitespace followed by a period
            if (lastChar == '.' && Character.isWhitespace(nowChar))
                return __text.substring(0, i);
            
            // Set new last character
            lastChar = nowChar;
        }
        
        // If this point was reached, entire is used
        return __text;
    }
    
    /**
     * Neatens the text so it does not look horrible.
     * 
     * @param __text The text to neaten.
     * @return The neatened text.
     * @since 2022/08/24
     */
    public static String neatText(String __text)
    {
        // If null, just carry it over
        if (__text == null)
            return null;
        
        StringBuilder result = new StringBuilder(__text.length());
        
        // Process every character
        char lastChar = 0xFFFD;
        boolean useChar;
        for (int i = 0, n = __text.length(); i < n; i++)
        {
            // Use the character by default
            useChar = true;
            char nowChar = __text.charAt(i);
            
            // Normalize any and all whitespace to just space
            if (Character.isWhitespace(nowChar))
                nowChar = ' ';
            
            // If there is whitespace after whitespace, trim it down to just
            // a single one...
            if (lastChar == ' ' && nowChar == ' ')
                useChar = false;
            
            // Use character?
            if (useChar)
                result.append(nowChar);
            
            // Set last character for processing
            lastChar = nowChar;
        }
        
        return result.toString();
    }
    
    /**
     * Returns the relative path to another document.
     * 
     * @param __from The source path.
     * @param __to The target path.
     * @return The relative string to the path for usage in the document.
     * @throws NullPointerException On null arguments.
     * @since 2022/08/24
     */
    public static String relativePath(Path __from, Path __to)
        throws NullPointerException
    {
        if (__from == null || __to == null)
            throw new NullPointerException("NARG");
        
        // We want to stay in the same directory
        if (!Files.isDirectory(__from))
            __from = __from.getParent();
        
        // Build path
        StringBuilder sb = new StringBuilder();
        for (Path fragment : __from.relativize(__to))
        {
            if (sb.length() > 0)
                sb.append('/');
            
            sb.append(fragment.getFileName());
        }
        
        return sb.toString();
    }
    
    /**
     * Writes a link to another class.
     *
     * @param __writer The writer to write to.
     * @param __from The class we are coming from.
     * @param __class The class to target.
     * @throws IOException On write errors.
     * @throws NullPointerException On null arguments.
     * @since 2022/08/27
     */
    public static void writerLinkTo(MarkdownWriter __writer,
        ProcessedClass __from, ProcessedClass __class)
        throws IOException, NullPointerException
    {
        if (__writer == null || __from == null || __class == null)
            throw new NullPointerException("NARG");
        
        // If this class is invisible, then hide it from existence and go up
        if (!__class._isVisible)
        {
            // Try going to the super class instead
            ProcessedClass superClass = __class.superClass();
            if (superClass != null)
            {
                Utilities.writerLinkTo(__writer, __from, superClass);
                return;
            }
            
            // Otherwise, refer to object if this is not object
            else if (!__class.name.isObjectClass())
            {
                Utilities.writerLinkTo(__writer, __from,
                    __from.doclet().processClass(
                        __from.classDoc.findClass("java.lang.Object")));
                return;
            }
        }
        
        // Is within our own documentation tree?
        if (__class._implicit)
        {
            // Write direct link to it
            __writer.uri(Utilities.relativePath(__from._documentPath,
                __class._documentPath), __class.name.simpleName().toString());
            
            return;
        }
        
        // Points outside our documentation tree? Try to locate it        
        RemoteClass remoteClass = __from.doclet()
            .remoteClassProject(__class.name.toRuntimeString());
        if (remoteClass != null)
        {
            // Write longer relative link to it
            __writer.uri(Utilities.relativePath(__from._documentPath,
                __from.doclet().outputDir) + "/../" + remoteClass.projectName +
                "/" + remoteClass.markdownPath,
                __class.name.simpleName().toString());
            
            return;
        }
        
        // Could not figure out the location, so just use the binary name
        __writer.printf(true, "`%s`",
            __class.name.toRuntimeString());
    }
}