Skip to content

Enabling require-jsdoc applies fixes oddly on exported functions #526

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sheuertz opened this issue May 6, 2020 · 5 comments
Closed

Enabling require-jsdoc applies fixes oddly on exported functions #526

sheuertz opened this issue May 6, 2020 · 5 comments
Labels

Comments

@sheuertz
Copy link

sheuertz commented May 6, 2020

Hi,

When I enable require-jsdoc, for any of my exported functions, anything that is seen as needing fixed is injected between the export and const keywords. Additionally, for any functions that have parameters, it repeatedly adds "eeeeee" to the description block. I am using eslint 6.8.0, and eslint-plugin-jsdoc 24.0.2. Thank you.

My .eslintrc.js:

const config = {
    extends: [
        'eslint:recommended',
        'plugin:@typescript-eslint/eslint-recommended',
        'plugin:@typescript-eslint/recommended',
        'prettier/@typescript-eslint',
        'plugin:prettier/recommended',
        'plugin:react/recommended',
        'plugin:jest/recommended',
        'plugin:jest/style',
        'plugin:jsdoc/recommended',
        'plugin:import/errors',
        'plugin:import/warnings',
        'plugin:import/typescript',
    ],
    env: {
        browser: true,
        node: true,
        es6: true,
    },
    parser: '@typescript-eslint/parser',
    plugins: ['@typescript-eslint', 'react', 'jest', 'jsdoc', 'eslint-plugin-tsdoc', 'spellcheck'],
    parserOptions: {
        ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
        sourceType: 'module', // Allows for the use of imports
        ecmaFeatures: {
            jsx: true, // Allows for the parsing of JSX
        },
    },
    settings: {
        react: {
            version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
        },
        jsdoc: {
            mode: 'typescript',
        },
    },
    rules: {
        'jsdoc/no-undefined-types': 0, // JSDoc doesn't follow Typescript imports at this time. https://github.com/jsdoctypeparser/jsdoctypeparser/issues/50
        'jsdoc/require-description-complete-sentence': 1,
        'jsdoc/require-description': 1,
        'jsdoc/check-tag-names': ['error', { definedTags: ['jsx'] }],
        // Still not working. https://github.com/gajus/eslint-plugin-jsdoc/issues/524
        'jsdoc/require-jsdoc': [
            1,
            {
                require: {
                    ArrowFunctionExpression: true,
                    ClassDeclaration: true,
                    ClassExpression: true,
                    FunctionDeclaration: true,
                    FunctionExpression: true,
                    MethodDefinition: true
                },
            },
        ],
        'spellcheck/spell-checker': [
            1,
            {
                comments: true,
                strings: true,
                identifiers: true,
                lang: 'en_US',
                skipWords: [
                    'utils',
                    'eslint',
                    'enum',
                    'init',
                    'noms',
                    'redux',
                    'nullable',
                    'memberof',
                    'param',
                    'middleware',
                    'unshift',
                    'commonjs',
                    'cjs',
                    'http',
                    'rollup',
                    'namespace',
                    'namespaces',
                    'xpath',
                    'html',
                    'textarea',
                    'src',
                    'truthy',
                    'falsy',
                    'mugu',
                    'jwt',
                    'px',
                    'img',
                    'rgb',
                    'svg',
                    'serializer',
                    'https',
                    'wss',
                    'png',
                    'rgba',
                    'grayscale',
                    'jsx',
                    'mailto',
                    'matchers',
                    'unmount',
                    'jsdoc',
                    'checkbox',
                    'dropdown',
                    'postcss',
                    'nowrap',
                    'params',
                    'auth',
                    'urlencoded',
                    'www',
                    'charset'
                ],
                skipIfMatch: [
                    'https?://[^s]*',
                    '^[-\\w]+/[-\\w\\.]+$', //For MIME Types
                ],
                minLength: 3,
            },
        ],
    },
};

module.exports = config;

For example:

Before:

/**
 * An action called when the user has successfully logged in.
 */
export const loginSuccessAction = (): BaseActionPayload => ({ type: LOGIN_SUCCESSFUL });

/**
 * An action called when the user has failed to log in.
 */
export const loginFailureAction = (error: string): ErrorPayload => ({ error, type: LOGIN_FAILURE });

/**
 * An action called when the application has successfully refreshed the user's JSON Web Token (JWT).
 */
export const refreshSuccessAction = (): BaseActionPayload => ({ type: REFRESH_SUCCESSFUL });

/**
 * An action called when the application has failed to refresh the user's JSON Web Token (JWT).
 */
export const refreshFailureAction = (error: string): ErrorPayload => ({
    type: REFRESH_FAILURE,
    error,
});

export const clearErrorMessageAction = (): BaseActionPayload => ({ type: CLEAR_ERROR_MESSAGE });

/**
 * An action called to notify that the application is beginning to refresh the user's JSON Web Token (JWT).
 */
export const startRefreshAction = (): BaseActionPayload => ({ type: START_REFRESH });

/**
 * An action called when the user logs out of the application.
 */
export const logoutAction = (): BaseActionPayload => ({ type: LOGOUT });

/**
 * Logs the user out of the system and redirects to the log in page.
 *
 * @returns {(dispatch: Dispatch<BaseActionPayload>) => void}
 */
export const logout = (): ((dispatch: Dispatch<BaseActionPayload>) => void) => {
    return (dispatch: Dispatch<BaseActionPayload>): void => {
        sessionStorage.removeItem('jwt');
        Promise.all([dispatch(logoutAction())]).then((): void => History.instance.push('/Login'));
    };
};

/**
 * Attempts to log the user in to the application. If successful, the loginSuccessAction is dispatched,
 * otherwise the loginFailureAction is dispatched.
 *
 * @param {string} username The user's username.
 * @param {string} password The user's password.
 * @param {string} [logInWithCAC=false] If true, log in using a CAC/2FA token instead of a username and password.
 * @returns {(dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void}
 */
export const login = (
    username: string,
    password: string,
    logInWithCAC = false,
): ((dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void) => {
    return (dispatch: Dispatch<ErrorPayload | BaseActionPayload>): void => {
        dispatch(clearErrorMessageAction());
        makeOAuthCall(username, password, null, logInWithCAC)
            .then(
                (response: Response): Promise<JWT> => {
                    // 2XX response, we're good here.
                    if (response.status >= 200 && response.status < 300) {
                        return response.json();
                    }
                    throw new Error('Log in failed');
                },
            )
            .then(
                (jwt: JWT): BaseActionPayload => {
                    sessionStorage.setItem('jwt', JSON.stringify(jwt));
                    return dispatch(loginSuccessAction());
                },
            )
            .catch(
                (exception: Error): ErrorPayload => {
                    return dispatch(loginFailureAction(exception.message));
                },
            );
    };
};

/**
 * Attempts to refresh the user's access, and generate a new JSON Web Token (JWT).
 *
 * @returns {(dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void} The dispatch function to be used to refresh the user's token.
 */
export const refresh = (): ((dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void) => {
    return (dispatch: Dispatch<ErrorPayload | BaseActionPayload>): void => {
        const jwt = getJwt();
        if (jwt) {
            dispatch(clearErrorMessageAction());
            dispatch(startRefreshAction());
            makeOAuthCall(null, null, jwt.refresh_token)
                .then(
                    (response: Response): Promise<JWT> => {
                        // 2XX response, we're good here.
                        if (Math.trunc(response.status / 200) === 1) {
                            return response.json();
                        }
                        throw new Error('Refresh failed');
                    },
                )
                .then(
                    (jwt: JWT): BaseActionPayload => {
                        sessionStorage.setItem('jwt', JSON.stringify(jwt));
                        return dispatch(refreshSuccessAction());
                    },
                )
                .catch(
                    (exception: Error): ErrorPayload => {
                        return dispatch(refreshFailureAction(exception.message));
                    },
                );
        }
    };
};

After:

...
/**
 * An action called when the user has successfully logged in.
 */
export /**
 *
 */
const loginSuccessAction = (): BaseActionPayload => ({ type: LOGIN_SUCCESSFUL });

/**
 * An action called when the user has failed to log in.
 */
export /**
 * Eeeeeee * Eeeeeee * Eeeeeee.
* Eeeeeee * Eeeeeee *
* Eeeeeee * Eeeeeee * @param error
* eeeeeee * eeeeeee eeeeeee.
* eeeeeee *
* eeeeeee * @param error
* eeeeeee eeeeeee.
 *
 * @param error
 */
const loginFailureAction = (error: string): ErrorPayload => ({ error, type: LOGIN_FAILURE });

/**
 * An action called when the application has successfully refreshed the user's JSON Web Token (JWT).
 */
export /**
 *
 */
const refreshSuccessAction = (): BaseActionPayload => ({ type: REFRESH_SUCCESSFUL });

/**
 * An action called when the application has failed to refresh the user's JSON Web Token (JWT).
 */
export /**
 * Eeeeeee * Eeeeeee * Eeeeeee.
* Eeeeeee * Eeeeeee *
* Eeeeeee * Eeeeeee * @param error
* eeeeeee * eeeeeee eeeeeee.
* eeeeeee *
* eeeeeee * @param error
* eeeeeee eeeeeee.
 *
 * @param error
 */
const refreshFailureAction = (error: string): ErrorPayload => ({
    type: REFRESH_FAILURE,
    error,
});

export /**
 *
 */
const clearErrorMessageAction = (): BaseActionPayload => ({ type: CLEAR_ERROR_MESSAGE });

/**
 * An action called to notify that the application is beginning to refresh the user's JSON Web Token (JWT).
 */
export /**
 *
 */
const startRefreshAction = (): BaseActionPayload => ({ type: START_REFRESH });

/**
 * An action called when the user logs out of the application.
 */
export /**
 *
 */
const logoutAction = (): BaseActionPayload => ({ type: LOGOUT });

/**
 * Logs the user out of the system and redirects to the log in page.
 *
 * @returns {(dispatch: Dispatch<BaseActionPayload>) => void}
 */
export /**
 *
 */
const logout = (): ((dispatch: Dispatch<BaseActionPayload>) => void) => {
    return (dispatch: Dispatch<BaseActionPayload>): void => {
        sessionStorage.removeItem('jwt');
        Promise.all([dispatch(logoutAction())]).then((): void => History.instance.push('/Login'));
    };
};

/**
 * Attempts to log the user in to the application. If successful, the loginSuccessAction is dispatched,
 * otherwise the loginFailureAction is dispatched.
 *
 * @param {string} username The user's username.
 * @param {string} password The user's password.
 * @param {string} [logInWithCAC=false] If true, log in using a CAC/2FA token instead of a username and password.
 * @returns {(dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void}
 */
export /**
 * Eeeeeee * Eeeeeee * Eeeeeee.
* Eeeeeee * Eeeeeee *
* Eeeeeee * Eeeeeee * @param username
* eeeeeee * eeeeeee * @param password
* eeeeeee * eeeeeee * @param logInWithCAC
* eeeeeee * eeeeeee eeeeeee.
* eeeeeee *
* eeeeeee * @param username
* eeeeeee * @param password
* eeeeeee * @param logInWithCAC
* eeeeeee eeeeeee.
 *
 * @param username
 * @param password
 * @param logInWithCAC
 */
const login = (
    username: string,
    password: string,
    logInWithCAC = false,
): ((dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void) => {
    return (dispatch: Dispatch<ErrorPayload | BaseActionPayload>): void => {
        dispatch(clearErrorMessageAction());
        makeOAuthCall(username, password, null, logInWithCAC)
            .then(
                (response: Response): Promise<JWT> => {
                    // 2XX response, we're good here.
                    if (response.status >= 200 && response.status < 300) {
                        return response.json();
                    }
                    throw new Error('Log in failed');
                },
            )
            .then(
                (jwt: JWT): BaseActionPayload => {
                    sessionStorage.setItem('jwt', JSON.stringify(jwt));
                    return dispatch(loginSuccessAction());
                },
            )
            .catch(
                (exception: Error): ErrorPayload => {
                    return dispatch(loginFailureAction(exception.message));
                },
            );
    };
};

/**
 * Attempts to refresh the user's access, and generate a new JSON Web Token (JWT).
 *
 * @returns {(dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void} The dispatch function to be used to refresh the user's token.
 */
export /**
 *
 */
const refresh = (): ((dispatch: Dispatch<ErrorPayload | BaseActionPayload>) => void) => {
    return (dispatch: Dispatch<ErrorPayload | BaseActionPayload>): void => {
        const jwt = getJwt();
        if (jwt) {
            dispatch(clearErrorMessageAction());
            dispatch(startRefreshAction());
            makeOAuthCall(null, null, jwt.refresh_token)
                .then(
                    (response: Response): Promise<JWT> => {
                        // 2XX response, we're good here.
                        if (Math.trunc(response.status / 200) === 1) {
                            return response.json();
                        }
                        throw new Error('Refresh failed');
                    },
                )
                .then(
                    (jwt: JWT): BaseActionPayload => {
                        sessionStorage.setItem('jwt', JSON.stringify(jwt));
                        return dispatch(refreshSuccessAction());
                    },
                )
                .catch(
                    (exception: Error): ErrorPayload => {
                        return dispatch(refreshFailureAction(exception.message));
                    },
                );
        }
    };
};

@brettz9 brettz9 closed this as completed in 757d97a May 6, 2020
@gajus
Copy link
Owner

gajus commented May 6, 2020

🎉 This issue has been resolved in version 24.0.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

@gajus gajus added the released label May 6, 2020
@brettz9
Copy link
Collaborator

brettz9 commented May 6, 2020

Though I think it should, please let us know if the latest fix still doesn't address all of your issues (and which ones). Thanks!

brettz9 added a commit to brettz9/eslint-plugin-jsdoc that referenced this issue May 6, 2020
* master:
  fix: in conjunction with `comment-parser` update, remove last line break in last tag description for proper stringification (and fix old tests)
  test(no-types): check the fix for no-types preserves asterisks
  fix(require-jsdoc): check above export for named exports; fixes gajus#526

# Conflicts:
#	test/rules/assertions/requireParam.js
@brettz9
Copy link
Collaborator

brettz9 commented May 6, 2020

If you already updated, please update further to 24.0.6 as it includes some fixes for a regression introduced in the commit for this issue.

@sheuertz
Copy link
Author

sheuertz commented May 6, 2020

Perfect thank you!

@gajus
Copy link
Owner

gajus commented May 9, 2020

🎉 This issue has been resolved in version 25.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants