@@ -322,102 +322,10 @@ impl symBuilder {
322322 unsafe { pushSuggestion(&self.errors[len(self.errors)-1], fmt, args...) }
323323 }
324324
325- fn checkCppUseDeclPath(mut *self, decl: &ast::Use, path: str): (ok: bool) {
326- ext := filepath::Ext(path)
327- if !build::IsValidHeaderExt(ext) && !build::IsValidCppExt(ext) {
328- self.pushErr(decl.Token, "invalid C/C++ extension: "+conv::Quote(ext))
329- ret false
330- }
331-
332- // Exist?
333- info := os::Stat(path) else {
334- self.pushErr(decl.Token, "path not found or cannot be accessed: "+decl.Path.Kind)
335- ret false
336- }
337- if !info.Mode().IsRegular() {
338- self.pushErr(decl.Token, "path not found or cannot be accessed: "+decl.Path.Kind)
339- ret false
340- }
341-
342- ret true
343- }
344-
345- fn buildCppHeaderImport(mut *self, mut decl: &ast::Use): &ImportInfo {
346- mut path := decl.Path.Kind[1 : len(decl.Path.Kind)-1] // remove quotes
347-
348- if !build::IsStdHeaderPath(path) {
349- // If there is no module, no common directories.
350- // For the local packages, the root package needs a module.
351- mut mod := self.importer.GetMod()
352- if mod == nil {
353- self.pushErr(decl.Path, "module not found")
354- self.pushSuggestion(`run "julec mod init <modulename>" to initialize a bind module in the current directory`)
355- ret nil
356- }
357-
358- // Take module name and submodule path from the path.
359- pathModName, (path) := splitModuleNameFromFilepath(path)
360-
361- // All import filepaths are must be start with module name.
362- if mod.Name != pathModName {
363- self.pushErr(decl.Path, "import path must use the root name of the module")
364- self.pushSuggestion("module name of this package is: " + conv::Quote(mod.Name))
365- ret nil
366- }
367-
368- // Join path with the absolute module path and
369- // make sure we have an absolute path to the package.
370- path = filepath::Join(mod.Path, path)
371- path = filepath::Abs(path) else {
372- self.pushErr(decl.Path, "path not found or cannot be accessed: "+decl.Path.Kind)
373- ret nil
374- }
375-
376- mut ok := self.checkCppUseDeclPath(decl, path)
377- if !ok {
378- ret nil
379- }
380-
381- // Set to absolute path for correct include path.
382- path = filepath::Abs(path) else {
383- self.pushErr(decl.Token, "path not found or cannot be accessed: "+decl.Path.Kind)
384- use ""
385- }
386- }
387-
388- ret &ImportInfo{
389- Decl: decl,
390- Path: path,
391- LinkPath: decl.Path.Kind,
392- Bind: true,
393- Std: false,
394- Package: nil, // Cpp headers haven't symbol table.
395- }
396- }
397-
398325 // Checks and returns absolute path of import filepath.
399326 // Designed for non-std package paths.
400327 // Returns empty string if error occurs.
401- fn checkAbsPath(mut &self, mut filepath: str, mut decl: &ast::Use): str {
402- // If there is no module, no common directories.
403- // For the local packages, the root package needs a module.
404- mut mod := self.importer.GetMod()
405- if mod == nil {
406- self.pushErr(decl.Path, "module not found")
407- self.pushSuggestion(`run "julec mod init <modulename>" to initialize a module in the current directory`)
408- ret ""
409- }
410-
411- // Take module name and submodule path from the filepath.
412- filepathModName, filepath := splitModuleNameFromFilepath(filepath)
413-
414- // All import filepaths are must be start with module name.
415- if mod.Name != filepathModName {
416- self.pushErr(decl.Path, "import path must use the root name of the module")
417- self.pushSuggestion("module name of this package is: " + conv::Quote(mod.Name))
418- ret ""
419- }
420-
328+ fn checkAbsPath(mut &self, mut filepath: str, mut decl: &ast::Use, mod: &mod::Mod): str {
421329 // Join filepath with the absolute module path and
422330 // make sure we have an absolute path to the package.
423331 filepath = filepath::Join(mod.Path, filepath)
@@ -426,72 +334,84 @@ impl symBuilder {
426334 ret ""
427335 }
428336
429- // Check the absolute path is exist and a directory (package).
430- info := os::Stat(filepath) else {
431- self.pushErr(decl.Path, "path not found or cannot be accessed: "+decl.Path.Kind)
432- ret ""
433- }
434- if !info.IsDir() {
435- self.pushErr(decl.Path, "path not found or cannot be accessed: "+decl.Path.Kind)
436- ret ""
437- }
438-
439337 ret filepath
440338 }
441339
442340 // Same as the [checkAbsPath] method but designed for std package paths.
443341 fn checkStdAbsPath(mut &self, mut filepath: str, mut decl: &ast::Use): str {
444- if filepath == "std " {
342+ if filepath == "" {
445343 self.pushErr(decl.Path, "invalid import path: "+decl.Path.Kind)
446344 ret ""
447345 }
448- filepath = filepath[len("std")+1:] // cut "std" + pathsep prefix
449346 filepath = filepath::Join(build::PathStdlib(), filepath)
450347 filepath = filepath::Abs(filepath) else {
451348 self.pushErr(decl.Path, "path not found or cannot be accessed: "+decl.Path.Kind)
452349 ret ""
453350 }
454351
455- // Exist?
456- info := os::Stat(filepath) else {
457- self.pushErr(decl.Path, "path not found or cannot be accessed: "+decl.Path.Kind)
458- ret ""
459- }
460- if !info.IsDir() {
461- self.pushErr(decl.Path, "path not found or cannot be accessed: "+decl.Path.Kind)
462- ret ""
463- }
464-
465352 ret filepath
466353 }
467354
468355 // Checks import path and returns as filepath if no error exist.
469356 fn checkImpPath(mut &self, mut decl: &ast::Use): (std: bool, filepath: str) {
470357 path := decl.Path.Kind[1 : len(decl.Path.Kind)-1] // remove quotes
471- if strings::HasSuffix(path, jule::ImportPathSep) {
472- self.pushErr(decl.Path, "invalid import path: "+decl.Path.Kind)
473- ret
358+ if decl.Bind && build::IsStdHeaderPath(path) {
359+ ret false, path
474360 }
475- parts := strings::Split(path, jule::ImportPathSep)
476- if len(parts) == 0 {
361+
362+ // Take module name and submodule path from the import path.
363+ pathModName, submodulePath := splitModuleNameFromFilepath(path)
364+ std = pathModName == build::ModStdlib().Name
365+
366+ filepath = checkImportPathValidity(submodulePath)
367+ if filepath == "" {
477368 self.pushErr(decl.Path, "invalid import path: "+decl.Path.Kind)
478- ret
479- }
480- std = parts[0] == "std"
481- for _, part in parts {
482- if part == "" || jule::IsBlank(part) || strings::ContainsRune(part, '.') {
483- self.pushErr(decl.Path, "invalid import path: "+decl.Path.Kind)
484- ret false, ""
485- }
486- filepath = filepath::Join(filepath, part)
369+ ret false, ""
487370 }
488371
489372 // build absolute path
490373 if std {
491374 filepath = self.checkStdAbsPath(filepath, decl)
492375 } else {
493- filepath = self.checkAbsPath(filepath, decl)
376+ // If there is no module, no common directories.
377+ // For the local packages, the root package needs a module.
378+ mut mod := self.importer.GetMod()
379+ if mod == nil {
380+ self.pushErr(decl.Path, "module not found")
381+ self.pushSuggestion(`run "julec mod init <modulename>" to initialize a module in the current directory`)
382+ ret false, ""
383+ }
384+
385+ // All import filepaths are must be start with module name.
386+ if mod.Name != pathModName {
387+ self.pushErr(decl.Path, "import path must use the root name of the module")
388+ self.pushSuggestion("module name of this package is: " + conv::Quote(mod.Name))
389+ ret false, ""
390+ }
391+
392+ filepath = self.checkAbsPath(filepath, decl, mod)
494393 }
394+
395+ if decl.Bind {
396+ ext := filepath::Ext(filepath)
397+ if !build::IsValidHeaderExt(ext) && !build::IsValidCppExt(ext) {
398+ self.pushErr(decl.Token, "invalid C/C++ extension: "+conv::Quote(ext))
399+ ret false, ""
400+ }
401+ }
402+
403+ // Exist?
404+ info := os::Stat(filepath) else {
405+ self.pushErr(decl.Token, "path not found or cannot be accessed: "+decl.Path.Kind)
406+ ret false, ""
407+ }
408+ exist := !decl.Bind && info.IsDir() ||
409+ decl.Bind && info.Mode().IsRegular()
410+ if !exist {
411+ self.pushErr(decl.Token, "path not found or cannot be accessed: "+decl.Path.Kind)
412+ ret false, ""
413+ }
414+
495415 ret
496416 }
497417
@@ -504,9 +424,6 @@ impl symBuilder {
504424 }
505425
506426 fn buildImport(mut &self, mut decl: &ast::Use): &ImportInfo {
507- if decl.Bind {
508- ret self.buildCppHeaderImport(decl)
509- }
510427 std, filepath := self.checkImpPath(decl)
511428 if filepath == "" { // error occurred
512429 ret nil
@@ -516,11 +433,17 @@ impl symBuilder {
516433 Decl: decl,
517434 Path: filepath,
518435 LinkPath: decl.Path.Kind[1 : len(decl.Path.Kind)-1],
519- Bind: false,
520436 Std: std,
521- Package: &Package{
522- Files: nil, // Appends by import algorithm.
523- },
437+ }
438+
439+ if decl.Bind {
440+ imp.Bind = true
441+ imp.Package = nil // Cpp headers haven't symbol table.
442+ ret imp
443+ }
444+
445+ imp.Package = &Package{
446+ Files: nil, // Appends by import algorithm.
524447 }
525448 if decl.Alias != nil {
526449 imp.Alias = decl.Alias.Kind
@@ -827,4 +750,23 @@ fn splitModuleNameFromFilepath(filepath: str): (modName: str, submodulePath: str
827750 submodulePath = ""
828751 }
829752 ret
753+ }
754+
755+ // Checks validity of the import path and returns it as filepath.
756+ // Returns empty string if path is invalid.
757+ fn checkImportPathValidity(path: str): (filepath: str) {
758+ if strings::HasSuffix(path, jule::ImportPathSep) {
759+ ret ""
760+ }
761+ parts := strings::Split(path, jule::ImportPathSep)
762+ if len(parts) == 0 {
763+ ret ""
764+ }
765+ for _, part in parts {
766+ if part == "" || jule::IsBlank(part) || strings::ContainsAny(part, "\\") {
767+ ret ""
768+ }
769+ filepath = filepath::Join(filepath, part)
770+ }
771+ ret filepath
830772}
0 commit comments