sveltejs / language-tools

The Svelte Language Server, and official extensions which use it
MIT License
1.26k stars 200 forks source link

autcomplete for module names is not working #430

Closed AhmadMayo closed 4 years ago

AhmadMayo commented 4 years ago

Describe the bug When I try to import any package, the editor doesn't suggest anything except "*.svelte" as the package name. Surprisingly when I type the name of any package, the intellisense works correctly for the exported variables and types.

To Reproduce

  1. Use svelte template
  2. Open App.svelte
  3. Type import x from"" and tap ctrl+space - or whatever open the suggestions list - when the cursor is between the quotes of the module name.

Expected behavior VSCode displays the names of the installed packages

Screenshots Screenshot from 2020-08-05 20-00-17 Screenshot from 2020-08-05 20-00-53 Screenshot from 2020-08-05 20-09-57 Screenshot from 2020-08-05 20-12-42

System (please complete the following information):

Additional context None

jasonlyu123 commented 4 years ago

I'm guessing this is because you run npm install after the extension is initialized. It that case the detection of node_modules is already finished. Due to the memory usage issues, we can't add all the added files to the compilation list but manual imported one is fine. If you restart your language-server after npm install it should work fine.

AhmadMayo commented 4 years ago

I tested your theory, but I think it's not totally correct. I have two folders, the first is just the empty template (14 dev deoendency and 1 dependency), and the other with installed packages (23 dev deps and 3 deps). It's working in the empty template project, but not the other.

From the plugin output tap:

SnapshotManager File Statistics:
Project files: 5
Svelte files: 12
From node_modules: 73
Total: 91

I don't thinks that's a lot of modules nor files, but may be I'm wrong. Can you guide me to get to the cause of the issue?

jasonlyu123 commented 4 years ago

73 seems reasonable to me, typescript will only grab the definition file when applicable. Does the one that is not working also built on top of the official template?

AhmadMayo commented 4 years ago

Yes, but I tweeked the config files a little.

tsconfig:

{
  "extends": "@tsconfig/svelte/tsconfig.json",

  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"],
  "compilerOptions": {
    "moduleResolution": "node",
    "target": "es2020",
    "importsNotUsedAsValues": "error",
    "isolatedModules": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "types": ["svelte"]
  },
}

rollup.config

import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import {terser} from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import postCSSImport from "postcss-import";
import replace from "@rollup/plugin-replace";
import json from '@rollup/plugin-json';
import svelteSVG from "rollup-plugin-svelte-svg";
import dotenv from 'dotenv-flow';
import dotenvExpand from 'dotenv-expand';
import config from './package.json';

dotenvExpand(dotenv.config());
const env = Object.fromEntries(
  Object.entries(process.env).filter(([key]) => key.startsWith('SVELTE_')),
);
env.VERSION = config.version;
env.PUBLIC_URL = config.homepage || '';

const production = !process.env.ROLLUP_WATCH;

function serve() {
  let server;

  function toExit() {
    if (server) server.kill(0);
  }

  return {
    writeBundle() {
      if (server) return;
      server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
        stdio: ['ignore', 'inherit', 'inherit'],
        shell: true,
      });

      process.on('SIGTERM', toExit);
      process.on('exit', toExit);
    },
  };
}

export default {
  input: 'src/main.ts',
  output: {
    sourcemap: true,
    format: 'es',
    name: 'app',
    dir: 'public/build/',
    manualChunks(id) {
      if (id.includes('node_modules')) {
        const pathSegments = id.replace(/.*node_modules\//, '').split('/');
        return pathSegments[0] + '/' + pathSegments.slice(1).join('-');
      }

      if (id.includes('/src/ui/')) {
        return 'ui/' + id.split('/').reverse()[0];
      }
    }
  },
  moduleContext: id => {
    const thisAsWindowForModules = 'node_modules/intl-';

    if (id.includes(thisAsWindowForModules)) {
      return 'window';
    }
  },
  plugins: [
    replace({'process.env': JSON.stringify(env)}),
    json(),
    svelteSVG(),
    svelte({
      // enable run-time checks when not in production
      dev: !production,
      // we'll extract any component CSS out into
      // a separate file - better for performance
      css: css => {
        css.write('public/build/bundle.css');
      },
      preprocess: sveltePreprocess({
        postcss: {
          plugins: [
            postCSSImport(),
          ],
        }
      }),
    }),

    // If you have external dependencies installed from
    // npm, you'll most likely need these plugins. In
    // some cases you'll need additional configuration -
    // consult the documentation for details:
    // https://github.com/rollup/plugins/tree/master/packages/commonjs
    resolve({
      browser: true,
      dedupe: ['svelte'],
    }),
    commonjs(),
    typescript({sourceMap: !production}),

    // In dev mode, call `npm run start` once
    // the bundle has been generated
    !production && serve(),

    // Watch the `public` directory and refresh the
    // browser on changes when not in production
    !production && livereload('public'),

    // If we're building for production (npm run build
    // instead of npm run dev), minify
    production && terser(),
  ],
  watch: {
    clearScreen: false,
  },
};
dummdidumm commented 4 years ago

Although this is fixed by us, you still need to adjust your tsconfig to get the desired behavior. Remove "types": ["svelte"] from your tsconfig and wait for this PR to land and update @tsconfig/svelte after it's released.

AhmadMayo commented 4 years ago

Thanks a lot

dummdidumm commented 4 years ago

I was too quick on "remove "type": ["svelte"] - that's needed for TS files to not error on .svelte imports. I'm not sure if you can get the desired behavior right now.

AhmadMayo commented 4 years ago

Thanks a lot for your time. Should we reopen? And is there anything I can do to help

dummdidumm commented 4 years ago

If I try to reproduce this with the starter template I get other suggestions besides *.svelte. Which suggestions are you missing in your case?

AhmadMayo commented 4 years ago

Everything. Even dev dependencies like typescript or rollup don't appear

dummdidumm commented 4 years ago

If I checkout the starter template, transform to TS, npm i, open App.svelte, then I get more than just *.svelte. I also get things such as typescript. I also get them when using your tsconfig.json.

AhmadMayo commented 4 years ago

It's probably related to the number of installed packages. I'll try to create a repo where I could reproduce the issue, but I will not be able to do it before tuesday

AhmadMayo commented 4 years ago

@dummdidumm I removed node_modules and package-lock.json in my project, reinstalled, restarted svelte server and now it works. May be your fix did solve it after all. Thank you very much for your time